Repository: google/go-github (go)

Issue:
Support preview enable/disable Pages API
GitHub Developer API announcement:
https://developer.github.com/changes/2019-03-14-enabling-disabling-pages/

This would be a great PR for any new contributor to this repo or a new Go developer.
All contributions are greatly appreciated!

Feel free to volunteer for any issue and the issue can be assigned to you so that others don't attempt to duplicate the work.

Please check out our [CONTRIBUTING.md](https://github.com/google/go-github/blob/master/CONTRIBUTING.md) guide to get started.

Thank you!


Pull request:
updated custom media type to Preview enable and disable Pages API
Fixes #1133 

Patch:
diff --git a/AUTHORS b/AUTHORS
index 1bde5b1f..c738851a 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -54,6 +54,7 @@ Charlie Yan <charlieyan08@gmail.com>
 Chris King <chriskingnet@gmail.com>
 Chris Roche <chris@vsco.co>
 Chris Schaefer <chris@dtzq.com>
+chrisforrette <chris@chrisforrette.com>
 Christoph Sassenberg <defsprite@gmail.com>
 Colin Misare <github.com/cmisare>
 Craig Peterson <cpeterson@stackoverflow.com>
@@ -117,6 +118,7 @@ Joan Saum <joan.saum@epitech.eu>
 Joe Tsai <joetsai@digital-static.net>
 John Barton <jrbarton@gmail.com>
 John Engelman <john.r.engelman@gmail.com>
+Jordan Brockopp <jdbro94@gmail.com>
 Jordan Sussman <jordansail22@gmail.com>
 Joshua Bezaleel Abednego <joshua.bezaleel@gmail.com>
 JP Phillips <jonphill9@gmail.com>
@@ -137,6 +139,7 @@ Kookheon Kwon <kucuny@gmail.com>
 Krzysztof Kowalczyk <kkowalczyk@gmail.com>
 Kshitij Saraogi <KshitijSaraogi@gmail.com>
 kyokomi <kyoko1220adword@gmail.com>
+Liam Galvin <liam@liam-galvin.co.uk>
 Lovro Mažgon <lovro.mazgon@gmail.com>
 Lucas Alcantara <lucasalcantaraf@gmail.com>
 Luke Evers <me@lukevers.com>
@@ -180,6 +183,7 @@ Rackspace US, Inc.
 Radek Simko <radek.simko@gmail.com>
 Radliński Ignacy <radlinsk@student.agh.edu.pl>
 Rajendra arora <rajendraarora16@yahoo.com>
+Ranbir Singh <binkkatal.r@gmail.com>
 RaviTeja Pothana <ravi-teja@live.com>
 rc1140 <jameel@republiccommandos.co.za>
 Red Hat, Inc.
@@ -214,6 +218,7 @@ Thomas Bruyelle <thomas.bruyelle@gmail.com>
 Timothée Peignier <timothee.peignier@tryphon.org>
 Trey Tacon <ttacon@gmail.com>
 ttacon <ttacon@gmail.com>
+Vaibhav Singh <vaibhav.singh.14cse@bml.edu.in>
 Varadarajan Aravamudhan <varadaraajan@gmail.com>
 Victor Castell <victor@victorcastell.com>
 Victor Vrantchan <vrancean+github@gmail.com>
@@ -225,5 +230,6 @@ xibz <impactbchang@gmail.com>
 Yann Malet <yann.malet@gmail.com>
 Yannick Utard <yannickutard@gmail.com>
 Yicheng Qin <qycqycqycqycqyc@gmail.com>
+Yosuke Akatsuka <yosuke.akatsuka@access-company.com>
 Yumikiyo Osanai <yumios.art@gmail.com>
 Zach Latta <zach@zachlatta.com>
diff --git a/github/apps.go b/github/apps.go
index ae3aabda..1ad9a981 100644
--- a/github/apps.go
+++ b/github/apps.go
@@ -62,6 +62,13 @@ type Installation struct {
 	UpdatedAt           *Timestamp               `json:"updated_at,omitempty"`
 }
 
+// Attachment represents a GitHub Apps attachment.
+type Attachment struct {
+	ID    *int64  `json:"id,omitempty"`
+	Title *string `json:"title,omitempty"`
+	Body  *string `json:"body,omitempty"`
+}
+
 func (i Installation) String() string {
 	return Stringify(i)
 }
@@ -183,6 +190,29 @@ func (s *AppsService) CreateInstallationToken(ctx context.Context, id int64) (*I
 	return t, resp, nil
 }
 
+// Create a new attachment on user comment containing a url.
+//
+// GitHub API docs: https://developer.github.com/v3/apps/#create-a-content-attachment
+func (s *AppsService) CreateAttachment(ctx context.Context, contentReferenceID int64, title, body string) (*Attachment, *Response, error) {
+	u := fmt.Sprintf("content_references/%v/attachments", contentReferenceID)
+	payload := &Attachment{Title: String(title), Body: String(body)}
+	req, err := s.client.NewRequest("POST", u, payload)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	// TODO: remove custom Accept headers when APIs fully launch.
+	req.Header.Set("Accept", mediaTypeReactionsPreview)
+
+	m := &Attachment{}
+	resp, err := s.client.Do(ctx, req, m)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return m, resp, nil
+}
+
 // FindOrganizationInstallation finds the organization's installation information.
 //
 // GitHub API docs: https://developer.github.com/v3/apps/#find-organization-installation
diff --git a/github/github-accessors.go b/github/github-accessors.go
index 10015590..241b682e 100644
--- a/github/github-accessors.go
+++ b/github/github-accessors.go
@@ -188,6 +188,30 @@ func (a *App) GetUpdatedAt() time.Time {
 	return *a.UpdatedAt
 }
 
+// GetBody returns the Body field if it's non-nil, zero value otherwise.
+func (a *Attachment) GetBody() string {
+	if a == nil || a.Body == nil {
+		return ""
+	}
+	return *a.Body
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (a *Attachment) GetID() int64 {
+	if a == nil || a.ID == nil {
+		return 0
+	}
+	return *a.ID
+}
+
+// GetTitle returns the Title field if it's non-nil, zero value otherwise.
+func (a *Attachment) GetTitle() string {
+	if a == nil || a.Title == nil {
+		return ""
+	}
+	return *a.Title
+}
+
 // GetApp returns the App field.
 func (a *Authorization) GetApp() *AuthorizationApp {
 	if a == nil {
@@ -2476,6 +2500,38 @@ func (d *DismissalRestrictionsRequest) GetUsers() []string {
 	return *d.Users
 }
 
+// GetDismissalCommitID returns the DismissalCommitID field if it's non-nil, zero value otherwise.
+func (d *DismissedReview) GetDismissalCommitID() string {
+	if d == nil || d.DismissalCommitID == nil {
+		return ""
+	}
+	return *d.DismissalCommitID
+}
+
+// GetDismissalMessage returns the DismissalMessage field if it's non-nil, zero value otherwise.
+func (d *DismissedReview) GetDismissalMessage() string {
+	if d == nil || d.DismissalMessage == nil {
+		return ""
+	}
+	return *d.DismissalMessage
+}
+
+// GetReviewID returns the ReviewID field if it's non-nil, zero value otherwise.
+func (d *DismissedReview) GetReviewID() int64 {
+	if d == nil || d.ReviewID == nil {
+		return 0
+	}
+	return *d.ReviewID
+}
+
+// GetState returns the State field if it's non-nil, zero value otherwise.
+func (d *DismissedReview) GetState() string {
+	if d == nil || d.State == nil {
+		return ""
+	}
+	return *d.State
+}
+
 // GetBody returns the Body field if it's non-nil, zero value otherwise.
 func (d *DraftReviewComment) GetBody() string {
 	if d == nil || d.Body == nil {
@@ -3692,6 +3748,14 @@ func (i *Invitation) GetLogin() string {
 	return *i.Login
 }
 
+// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise.
+func (i *Invitation) GetNodeID() string {
+	if i == nil || i.NodeID == nil {
+		return ""
+	}
+	return *i.NodeID
+}
+
 // GetRole returns the Role field if it's non-nil, zero value otherwise.
 func (i *Invitation) GetRole() string {
 	if i == nil || i.Role == nil {
@@ -4092,6 +4156,14 @@ func (i *IssueEvent) GetCreatedAt() time.Time {
 	return *i.CreatedAt
 }
 
+// GetDismissedReview returns the DismissedReview field.
+func (i *IssueEvent) GetDismissedReview() *DismissedReview {
+	if i == nil {
+		return nil
+	}
+	return i.DismissedReview
+}
+
 // GetEvent returns the Event field if it's non-nil, zero value otherwise.
 func (i *IssueEvent) GetEvent() string {
 	if i == nil || i.Event == nil {
@@ -5500,6 +5572,14 @@ func (n *NewPullRequest) GetBody() string {
 	return *n.Body
 }
 
+// GetDraft returns the Draft field if it's non-nil, zero value otherwise.
+func (n *NewPullRequest) GetDraft() bool {
+	if n == nil || n.Draft == nil {
+		return false
+	}
+	return *n.Draft
+}
+
 // GetHead returns the Head field if it's non-nil, zero value otherwise.
 func (n *NewPullRequest) GetHead() string {
 	if n == nil || n.Head == nil {
@@ -5548,6 +5628,14 @@ func (n *NewTeam) GetLDAPDN() string {
 	return *n.LDAPDN
 }
 
+// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise.
+func (n *NewTeam) GetNodeID() string {
+	if n == nil || n.NodeID == nil {
+		return ""
+	}
+	return *n.NodeID
+}
+
 // GetParentTeamID returns the ParentTeamID field if it's non-nil, zero value otherwise.
 func (n *NewTeam) GetParentTeamID() int64 {
 	if n == nil || n.ParentTeamID == nil {
@@ -6188,6 +6276,14 @@ func (p *Pages) GetHTMLURL() string {
 	return *p.HTMLURL
 }
 
+// GetSource returns the Source field.
+func (p *Pages) GetSource() *PagesSource {
+	if p == nil {
+		return nil
+	}
+	return p.Source
+}
+
 // GetStatus returns the Status field if it's non-nil, zero value otherwise.
 func (p *Pages) GetStatus() string {
 	if p == nil || p.Status == nil {
@@ -6276,6 +6372,22 @@ func (p *PagesError) GetMessage() string {
 	return *p.Message
 }
 
+// GetBranch returns the Branch field if it's non-nil, zero value otherwise.
+func (p *PagesSource) GetBranch() string {
+	if p == nil || p.Branch == nil {
+		return ""
+	}
+	return *p.Branch
+}
+
+// GetPath returns the Path field if it's non-nil, zero value otherwise.
+func (p *PagesSource) GetPath() string {
+	if p == nil || p.Path == nil {
+		return ""
+	}
+	return *p.Path
+}
+
 // GetTotalPages returns the TotalPages field if it's non-nil, zero value otherwise.
 func (p *PageStats) GetTotalPages() int {
 	if p == nil || p.TotalPages == nil {
@@ -7516,6 +7628,14 @@ func (p *PullRequestComment) GetInReplyTo() int64 {
 	return *p.InReplyTo
 }
 
+// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise.
+func (p *PullRequestComment) GetNodeID() string {
+	if p == nil || p.NodeID == nil {
+		return ""
+	}
+	return *p.NodeID
+}
+
 // GetOriginalCommitID returns the OriginalCommitID field if it's non-nil, zero value otherwise.
 func (p *PullRequestComment) GetOriginalCommitID() string {
 	if p == nil || p.OriginalCommitID == nil {
@@ -7772,6 +7892,14 @@ func (p *PullRequestReview) GetID() int64 {
 	return *p.ID
 }
 
+// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise.
+func (p *PullRequestReview) GetNodeID() string {
+	if p == nil || p.NodeID == nil {
+		return ""
+	}
+	return *p.NodeID
+}
+
 // GetPullRequestURL returns the PullRequestURL field if it's non-nil, zero value otherwise.
 func (p *PullRequestReview) GetPullRequestURL() string {
 	if p == nil || p.PullRequestURL == nil {
@@ -7948,6 +8076,14 @@ func (p *PullRequestReviewRequest) GetEvent() string {
 	return *p.Event
 }
 
+// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise.
+func (p *PullRequestReviewRequest) GetNodeID() string {
+	if p == nil || p.NodeID == nil {
+		return ""
+	}
+	return *p.NodeID
+}
+
 // GetDismissalRestrictionsRequest returns the DismissalRestrictionsRequest field.
 func (p *PullRequestReviewsEnforcementRequest) GetDismissalRestrictionsRequest() *DismissalRestrictionsRequest {
 	if p == nil {
@@ -9636,6 +9772,14 @@ func (r *RepositoryCommit) GetHTMLURL() string {
 	return *r.HTMLURL
 }
 
+// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise.
+func (r *RepositoryCommit) GetNodeID() string {
+	if r == nil || r.NodeID == nil {
+		return ""
+	}
+	return *r.NodeID
+}
+
 // GetSHA returns the SHA field if it's non-nil, zero value otherwise.
 func (r *RepositoryCommit) GetSHA() string {
 	if r == nil || r.SHA == nil {
@@ -10300,6 +10444,14 @@ func (r *RepoStatus) GetID() int64 {
 	return *r.ID
 }
 
+// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise.
+func (r *RepoStatus) GetNodeID() string {
+	if r == nil || r.NodeID == nil {
+		return ""
+	}
+	return *r.NodeID
+}
+
 // GetState returns the State field if it's non-nil, zero value otherwise.
 func (r *RepoStatus) GetState() string {
 	if r == nil || r.State == nil {
@@ -10340,6 +10492,14 @@ func (r *RequiredStatusChecksRequest) GetStrict() bool {
 	return *r.Strict
 }
 
+// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise.
+func (r *ReviewersRequest) GetNodeID() string {
+	if r == nil || r.NodeID == nil {
+		return ""
+	}
+	return *r.NodeID
+}
+
 // GetName returns the Name field if it's non-nil, zero value otherwise.
 func (s *ServiceHook) GetName() string {
 	if s == nil || s.Name == nil {
@@ -10796,6 +10956,14 @@ func (t *Team) GetName() string {
 	return *t.Name
 }
 
+// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise.
+func (t *Team) GetNodeID() string {
+	if t == nil || t.NodeID == nil {
+		return ""
+	}
+	return *t.NodeID
+}
+
 // GetOrganization returns the Organization field.
 func (t *Team) GetOrganization() *Organization {
 	if t == nil {
diff --git a/github/github.go b/github/github.go
index 4d86d76b..44f30944 100644
--- a/github/github.go
+++ b/github/github.go
@@ -131,6 +131,9 @@ const (
 
 	// https://developer.github.com/changes/2019-02-14-draft-pull-requests/
 	mediaTypeDraftPreview = "application/vnd.github.shadow-cat-preview+json"
+
+	// https://developer.github.com/changes/2019-03-14-enabling-disabling-pages/
+	mediaTypeEnablePagesAPIPreview = "application/vnd.github.switcheroo-preview+json"
 )
 
 // A Client manages communication with the GitHub API.
diff --git a/github/issues_events.go b/github/issues_events.go
index 6a43f106..4456d67e 100644
--- a/github/issues_events.go
+++ b/github/issues_events.go
@@ -63,20 +63,34 @@ type IssueEvent struct {
 	//     head_ref_deleted, head_ref_restored
 	//       The pull request’s branch was deleted or restored.
 	//
+	//    review_dismissed
+	//       The review was dismissed and `DismissedReview` will be populated below.
+	//
 	Event *string `json:"event,omitempty"`
 
 	CreatedAt *time.Time `json:"created_at,omitempty"`
 	Issue     *Issue     `json:"issue,omitempty"`
 
 	// Only present on certain events; see above.
-	Assignee    *User        `json:"assignee,omitempty"`
-	Assigner    *User        `json:"assigner,omitempty"`
-	CommitID    *string      `json:"commit_id,omitempty"`
-	Milestone   *Milestone   `json:"milestone,omitempty"`
-	Label       *Label       `json:"label,omitempty"`
-	Rename      *Rename      `json:"rename,omitempty"`
-	LockReason  *string      `json:"lock_reason,omitempty"`
-	ProjectCard *ProjectCard `json:"project_card,omitempty"`
+	Assignee        *User            `json:"assignee,omitempty"`
+	Assigner        *User            `json:"assigner,omitempty"`
+	CommitID        *string          `json:"commit_id,omitempty"`
+	Milestone       *Milestone       `json:"milestone,omitempty"`
+	Label           *Label           `json:"label,omitempty"`
+	Rename          *Rename          `json:"rename,omitempty"`
+	LockReason      *string          `json:"lock_reason,omitempty"`
+	ProjectCard     *ProjectCard     `json:"project_card,omitempty"`
+	DismissedReview *DismissedReview `json:"dismissed_review,omitempty"`
+}
+
+// DismissedReview represents details for 'dismissed_review' events.
+type DismissedReview struct {
+	// State represents the state of the dismissed review.
+	// Possible values are: "commented", "approved", and "changes_requested".
+	State             *string `json:"state,omitempty"`
+	ReviewID          *int64  `json:"review_id,omitempty"`
+	DismissalMessage  *string `json:"dismissal_message,omitempty"`
+	DismissalCommitID *string `json:"dismissal_commit_id,omitempty"`
 }
 
 // ListIssueEvents lists events for the specified issue.
diff --git a/github/pulls.go b/github/pulls.go
index 067e362b..b26f6c5c 100644
--- a/github/pulls.go
+++ b/github/pulls.go
@@ -216,6 +216,7 @@ type NewPullRequest struct {
 	Body                *string `json:"body,omitempty"`
 	Issue               *int    `json:"issue,omitempty"`
 	MaintainerCanModify *bool   `json:"maintainer_can_modify,omitempty"`
+	Draft               *bool   `json:"draft,omitempty"`
 }
 
 // Create a new pull request on the specified repository.
@@ -229,7 +230,8 @@ func (s *PullRequestsService) Create(ctx context.Context, owner string, repo str
 	}
 
 	// TODO: remove custom Accept header when this API fully launches.
-	req.Header.Set("Accept", mediaTypeLabelDescriptionSearchPreview)
+	acceptHeaders := []string{mediaTypeLabelDescriptionSearchPreview, mediaTypeDraftPreview}
+	req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
 
 	p := new(PullRequest)
 	resp, err := s.client.Do(ctx, req, p)
diff --git a/github/pulls_comments.go b/github/pulls_comments.go
index f3067762..8886c9d1 100644
--- a/github/pulls_comments.go
+++ b/github/pulls_comments.go
@@ -14,6 +14,7 @@ import (
 // PullRequestComment represents a comment left on a pull request.
 type PullRequestComment struct {
 	ID                  *int64     `json:"id,omitempty"`
+	NodeID              *string    `json:"node_id,omitempty"`
 	InReplyTo           *int64     `json:"in_reply_to_id,omitempty"`
 	Body                *string    `json:"body,omitempty"`
 	Path                *string    `json:"path,omitempty"`
diff --git a/github/pulls_reviewers.go b/github/pulls_reviewers.go
index a1d78531..beae953c 100644
--- a/github/pulls_reviewers.go
+++ b/github/pulls_reviewers.go
@@ -12,6 +12,7 @@ import (
 
 // ReviewersRequest specifies users and teams for a pull request review request.
 type ReviewersRequest struct {
+	NodeID        *string  `json:"node_id,omitempty"`
 	Reviewers     []string `json:"reviewers,omitempty"`
 	TeamReviewers []string `json:"team_reviewers,omitempty"`
 }
diff --git a/github/pulls_reviews.go b/github/pulls_reviews.go
index 57d3c635..c2924473 100644
--- a/github/pulls_reviews.go
+++ b/github/pulls_reviews.go
@@ -14,6 +14,7 @@ import (
 // PullRequestReview represents a review of a pull request.
 type PullRequestReview struct {
 	ID             *int64     `json:"id,omitempty"`
+	NodeID         *string    `json:"node_id,omitempty"`
 	User           *User      `json:"user,omitempty"`
 	Body           *string    `json:"body,omitempty"`
 	SubmittedAt    *time.Time `json:"submitted_at,omitempty"`
@@ -40,6 +41,7 @@ func (c DraftReviewComment) String() string {
 
 // PullRequestReviewRequest represents a request to create a review.
 type PullRequestReviewRequest struct {
+	NodeID   *string               `json:"node_id,omitempty"`
 	CommitID *string               `json:"commit_id,omitempty"`
 	Body     *string               `json:"body,omitempty"`
 	Event    *string               `json:"event,omitempty"`
diff --git a/github/repos_commits.go b/github/repos_commits.go
index a4c62159..83cdf5b3 100644
--- a/github/repos_commits.go
+++ b/github/repos_commits.go
@@ -17,6 +17,7 @@ import (
 // Note that it's wrapping a Commit, so author/committer information is in two places,
 // but contain different details about them: in RepositoryCommit "github details", in Commit - "git details".
 type RepositoryCommit struct {
+	NodeID      *string  `json:"node_id,omitempty"`
 	SHA         *string  `json:"sha,omitempty"`
 	Commit      *Commit  `json:"commit,omitempty"`
 	Author      *User    `json:"author,omitempty"`
diff --git a/github/repos_pages.go b/github/repos_pages.go
index 94a95f2b..28674130 100644
--- a/github/repos_pages.go
+++ b/github/repos_pages.go
@@ -8,15 +8,23 @@ package github
 import (
 	"context"
 	"fmt"
+	"strings"
 )
 
 // Pages represents a GitHub Pages site configuration.
 type Pages struct {
-	URL       *string `json:"url,omitempty"`
-	Status    *string `json:"status,omitempty"`
-	CNAME     *string `json:"cname,omitempty"`
-	Custom404 *bool   `json:"custom_404,omitempty"`
-	HTMLURL   *string `json:"html_url,omitempty"`
+	URL       *string      `json:"url,omitempty"`
+	Status    *string      `json:"status,omitempty"`
+	CNAME     *string      `json:"cname,omitempty"`
+	Custom404 *bool        `json:"custom_404,omitempty"`
+	HTMLURL   *string      `json:"html_url,omitempty"`
+	Source    *PagesSource `json:"source,omitempty"`
+}
+
+// PagesSource represents a GitHub page's source.
+type PagesSource struct {
+	Branch *string `json:"branch,omitempty"`
+	Path   *string `json:"path,omitempty"`
 }
 
 // PagesError represents a build error for a GitHub Pages site.
@@ -36,6 +44,45 @@ type PagesBuild struct {
 	UpdatedAt *Timestamp  `json:"updated_at,omitempty"`
 }
 
+// EnablePages enables GitHub Pages for the named repo.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/pages/#enable-a-pages-site
+func (s *RepositoriesService) EnablePages(ctx context.Context, owner, repo string) (*Pages, *Response, error) {
+	u := fmt.Sprintf("repos/%v/%v/pages", owner, repo)
+	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.
+	acceptHeaders := []string{mediaTypeEnablePagesAPIPreview, mediaTypePagesPreview}
+	req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
+
+	enable := new(Pages)
+	resp, err := s.client.Do(ctx, req, enable)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return enable, resp, nil
+}
+
+// DisablePages disables GitHub Pages for the named repo.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/pages/#disable-a-pages-site
+func (s *RepositoriesService) DisablePages(ctx context.Context, owner, repo string) (*Response, error) {
+	u := fmt.Sprintf("repos/%v/%v/pages", owner, repo)
+	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", mediaTypeEnablePagesAPIPreview)
+
+	return s.client.Do(ctx, req, nil)
+}
+
 // GetPagesInfo fetches information about a GitHub Pages site.
 //
 // GitHub API docs: https://developer.github.com/v3/repos/pages/#get-information-about-a-pages-site
diff --git a/github/repos_statuses.go b/github/repos_statuses.go
index c889b31d..6d6a0d2f 100644
--- a/github/repos_statuses.go
+++ b/github/repos_statuses.go
@@ -14,8 +14,9 @@ import (
 
 // RepoStatus represents the status of a repository at a particular reference.
 type RepoStatus struct {
-	ID  *int64  `json:"id,omitempty"`
-	URL *string `json:"url,omitempty"`
+	ID     *int64  `json:"id,omitempty"`
+	NodeID *string `json:"node_id,omitempty"`
+	URL    *string `json:"url,omitempty"`
 
 	// State is the current state of the repository. Possible values are:
 	// pending, success, error, or failure.
diff --git a/github/teams.go b/github/teams.go
index 97d038d9..45285426 100644
--- a/github/teams.go
+++ b/github/teams.go
@@ -22,6 +22,7 @@ type TeamsService service
 // manage access to an organization's repositories.
 type Team struct {
 	ID          *int64  `json:"id,omitempty"`
+	NodeID      *string `json:"node_id,omitempty"`
 	Name        *string `json:"name,omitempty"`
 	Description *string `json:"description,omitempty"`
 	URL         *string `json:"url,omitempty"`
@@ -55,9 +56,10 @@ func (t Team) String() string {
 
 // Invitation represents a team member's invitation status.
 type Invitation struct {
-	ID    *int64  `json:"id,omitempty"`
-	Login *string `json:"login,omitempty"`
-	Email *string `json:"email,omitempty"`
+	ID     *int64  `json:"id,omitempty"`
+	NodeID *string `json:"node_id,omitempty"`
+	Login  *string `json:"login,omitempty"`
+	Email  *string `json:"email,omitempty"`
 	// Role can be one of the values - 'direct_member', 'admin', 'billing_manager', 'hiring_manager', or 'reinstate'.
 	Role              *string    `json:"role,omitempty"`
 	CreatedAt         *time.Time `json:"created_at,omitempty"`
@@ -121,6 +123,7 @@ func (s *TeamsService) GetTeam(ctx context.Context, team int64) (*Team, *Respons
 
 // NewTeam represents a team to be created or modified.
 type NewTeam struct {
+	NodeID       *string  `json:"node_id,omitempty"`
 	Name         string   `json:"name"` // Name of the team. (Required.)
 	Description  *string  `json:"description,omitempty"`
 	Maintainers  []string `json:"maintainers,omitempty"`


Test patch:
diff --git a/github/apps_test.go b/github/apps_test.go
index a594eab3..8456662b 100644
--- a/github/apps_test.go
+++ b/github/apps_test.go
@@ -185,6 +185,28 @@ func TestAppsService_CreateInstallationToken(t *testing.T) {
 	}
 }
 
+func TestAppsService_CreateAttachement(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/content_references/11/attachments", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "POST")
+		testHeader(t, r, "Accept", mediaTypeReactionsPreview)
+
+		w.WriteHeader(http.StatusOK)
+		w.Write([]byte(`{"id":1,"title":"title1","body":"body1"}`))
+	})
+
+	got, _, err := client.Apps.CreateAttachment(context.Background(), 11, "title1", "body1")
+	if err != nil {
+		t.Errorf("CreateAttachment returned error: %v", err)
+	}
+
+	want := &Attachment{ID: Int64(1), Title: String("title1"), Body: String("body1")}
+	if !reflect.DeepEqual(got, want) {
+		t.Errorf("CreateAttachment = %+v, want %+v", got, want)
+	}
+}
 func TestAppsService_FindOrganizationInstallation(t *testing.T) {
 	client, mux, _, teardown := setup()
 	defer teardown()
diff --git a/github/gists_comments_test.go b/github/gists_comments_test.go
index d2f5a953..b4345c40 100644
--- a/github/gists_comments_test.go
+++ b/github/gists_comments_test.go
@@ -12,8 +12,64 @@ import (
 	"net/http"
 	"reflect"
 	"testing"
+	"time"
 )
 
+func TestGistComments_marshall(t *testing.T) {
+	testJSONMarshal(t, &GistComment{}, "{}")
+
+	createdAt := time.Date(2002, time.February, 10, 15, 30, 0, 0, time.UTC)
+
+	u := &GistComment{
+		ID:   Int64(1),
+		URL:  String("u"),
+		Body: String("test gist comment"),
+		User: &User{
+			Login:       String("ll"),
+			ID:          Int64(123),
+			AvatarURL:   String("a"),
+			GravatarID:  String("g"),
+			Name:        String("n"),
+			Company:     String("c"),
+			Blog:        String("b"),
+			Location:    String("l"),
+			Email:       String("e"),
+			Hireable:    Bool(true),
+			PublicRepos: Int(1),
+			Followers:   Int(1),
+			Following:   Int(1),
+			CreatedAt:   &Timestamp{referenceTime},
+			URL:         String("u"),
+		},
+		CreatedAt: &createdAt,
+	}
+
+	want := `{
+		"id": 1,
+		"url": "u",
+		"body": "test gist comment",
+		"user": {
+			"login": "ll",
+			"id": 123,
+			"avatar_url": "a",
+			"gravatar_id": "g",
+			"name": "n",
+			"company": "c",
+			"blog": "b",
+			"location": "l",
+			"email": "e",
+			"hireable": true,
+			"public_repos": 1,
+			"followers": 1,
+			"following": 1,
+			"created_at": ` + referenceTimeStr + `,
+			"url": "u"
+		},
+		"created_at": "2002-02-10T15:30:00Z"
+	}`
+
+	testJSONMarshal(t, u, want)
+}
 func TestGistsService_ListComments(t *testing.T) {
 	client, mux, _, teardown := setup()
 	defer teardown()
diff --git a/github/gists_test.go b/github/gists_test.go
index 3d31c9ac..2d79b8c5 100644
--- a/github/gists_test.go
+++ b/github/gists_test.go
@@ -15,6 +15,215 @@ import (
 	"time"
 )
 
+func TestGist_marshall(t *testing.T) {
+	testJSONMarshal(t, &Gist{}, "{}")
+
+	createdAt := time.Date(2010, time.February, 10, 10, 10, 0, 0, time.UTC)
+	updatedAt := time.Date(2010, time.February, 10, 10, 10, 0, 0, time.UTC)
+
+	u := &Gist{
+		ID:          String("i"),
+		Description: String("description"),
+		Public:      Bool(true),
+		Owner: &User{
+			Login:       String("ll"),
+			ID:          Int64(123),
+			AvatarURL:   String("a"),
+			GravatarID:  String("g"),
+			Name:        String("n"),
+			Company:     String("c"),
+			Blog:        String("b"),
+			Location:    String("l"),
+			Email:       String("e"),
+			Hireable:    Bool(true),
+			PublicRepos: Int(1),
+			Followers:   Int(1),
+			Following:   Int(1),
+			CreatedAt:   &Timestamp{referenceTime},
+			URL:         String("u"),
+		},
+		Files: map[GistFilename]GistFile{
+			"gistfile.py": {
+				Size:     Int(167),
+				Filename: String("gistfile.py"),
+				Language: String("Python"),
+				Type:     String("application/x-python"),
+				RawURL:   String("raw-url"),
+				Content:  String("c"),
+			},
+		},
+		Comments:   Int(1),
+		HTMLURL:    String("html-url"),
+		GitPullURL: String("gitpull-url"),
+		GitPushURL: String("gitpush-url"),
+		CreatedAt:  &createdAt,
+		UpdatedAt:  &updatedAt,
+		NodeID:     String("node"),
+	}
+
+	want := `{
+		"id": "i",
+		"description": "description",
+		"public": true,
+		"owner": {
+			"login": "ll",
+			"id": 123,
+			"avatar_url": "a",
+			"gravatar_id": "g",
+			"name": "n",
+			"company": "c",
+			"blog": "b",
+			"location": "l",
+			"email": "e",
+			"hireable": true,
+			"public_repos": 1,
+			"followers": 1,
+			"following": 1,
+			"created_at": ` + referenceTimeStr + `,
+			"url": "u"
+		},
+		"files": {
+			"gistfile.py": {
+				"size": 167,
+				"filename": "gistfile.py",
+				"language": "Python",
+				"type": "application/x-python",
+				"raw_url": "raw-url",
+				"content": "c"
+			}
+		},
+		"comments": 1,
+		"html_url": "html-url",
+		"git_pull_url": "gitpull-url",
+		"git_push_url": "gitpush-url",
+		"created_at": "2010-02-10T10:10:00Z",
+		"updated_at": "2010-02-10T10:10:00Z",
+		"node_id": "node"
+	}`
+
+	testJSONMarshal(t, u, want)
+}
+
+func TestGistCommit_marshall(t *testing.T) {
+	testJSONMarshal(t, &GistCommit{}, "{}")
+
+	u := &GistCommit{
+		URL:     String("u"),
+		Version: String("v"),
+		User: &User{
+			Login:       String("ll"),
+			ID:          Int64(123),
+			AvatarURL:   String("a"),
+			GravatarID:  String("g"),
+			Name:        String("n"),
+			Company:     String("c"),
+			Blog:        String("b"),
+			Location:    String("l"),
+			Email:       String("e"),
+			Hireable:    Bool(true),
+			PublicRepos: Int(1),
+			Followers:   Int(1),
+			Following:   Int(1),
+			CreatedAt:   &Timestamp{referenceTime},
+			URL:         String("u"),
+		},
+		ChangeStatus: &CommitStats{
+			Additions: Int(1),
+			Deletions: Int(1),
+			Total:     Int(2),
+		},
+		CommittedAt: &Timestamp{referenceTime},
+		NodeID:      String("node"),
+	}
+
+	want := `{
+		"url": "u",
+		"version": "v",
+		"user": {
+			"login": "ll",
+			"id": 123,
+			"avatar_url": "a",
+			"gravatar_id": "g",
+			"name": "n",
+			"company": "c",
+			"blog": "b",
+			"location": "l",
+			"email": "e",
+			"hireable": true,
+			"public_repos": 1,
+			"followers": 1,
+			"following": 1,
+			"created_at": ` + referenceTimeStr + `,
+			"url": "u"
+		},
+		"change_status": {
+			"additions": 1,
+			"deletions": 1,
+			"total": 2
+		},
+		"committed_at": ` + referenceTimeStr + `,
+		"node_id": "node"
+	}`
+
+	testJSONMarshal(t, u, want)
+}
+
+func TestGistFork_marshall(t *testing.T) {
+	testJSONMarshal(t, &GistFork{}, "{}")
+
+	u := &GistFork{
+		URL: String("u"),
+		User: &User{
+			Login:       String("ll"),
+			ID:          Int64(123),
+			AvatarURL:   String("a"),
+			GravatarID:  String("g"),
+			Name:        String("n"),
+			Company:     String("c"),
+			Blog:        String("b"),
+			Location:    String("l"),
+			Email:       String("e"),
+			Hireable:    Bool(true),
+			PublicRepos: Int(1),
+			Followers:   Int(1),
+			Following:   Int(1),
+			CreatedAt:   &Timestamp{referenceTime},
+			URL:         String("u"),
+		},
+		ID:        String("id"),
+		CreatedAt: &Timestamp{referenceTime},
+		UpdatedAt: &Timestamp{referenceTime},
+		NodeID:    String("node"),
+	}
+
+	want := `{
+		"url": "u",
+		"user": {
+			"login": "ll",
+			"id": 123,
+			"avatar_url": "a",
+			"gravatar_id": "g",
+			"name": "n",
+			"company": "c",
+			"blog": "b",
+			"location": "l",
+			"email": "e",
+			"hireable": true,
+			"public_repos": 1,
+			"followers": 1,
+			"following": 1,
+			"created_at": ` + referenceTimeStr + `,
+			"url": "u"
+		},
+		"id": "id",
+		"created_at": ` + referenceTimeStr + `,
+		"updated_at": ` + referenceTimeStr + `,
+		"node_id": "node"
+	}`
+
+	testJSONMarshal(t, u, want)
+}
+
 func TestGistsService_List_specifiedUser(t *testing.T) {
 	client, mux, _, teardown := setup()
 	defer teardown()
diff --git a/github/pulls_comments_test.go b/github/pulls_comments_test.go
index 76b78cf7..b07b2cd9 100644
--- a/github/pulls_comments_test.go
+++ b/github/pulls_comments_test.go
@@ -15,6 +15,106 @@ import (
 	"time"
 )
 
+func TestPullComments_marshall(t *testing.T) {
+	testJSONMarshal(t, &PullRequestComment{}, "{}")
+
+	createdAt := time.Date(2002, time.February, 10, 15, 30, 0, 0, time.UTC)
+	updatedAt := time.Date(2002, time.February, 10, 15, 30, 0, 0, time.UTC)
+	reactions := &Reactions{
+		TotalCount: Int(1),
+		PlusOne:    Int(1),
+		MinusOne:   Int(0),
+		Laugh:      Int(0),
+		Confused:   Int(0),
+		Heart:      Int(0),
+		Hooray:     Int(0),
+		URL:        String("u"),
+	}
+
+	u := &PullRequestComment{
+		ID:                  Int64(10),
+		InReplyTo:           Int64(8),
+		Body:                String("Test comment"),
+		Path:                String("file1.txt"),
+		DiffHunk:            String("@@ -16,33 +16,40 @@ fmt.Println()"),
+		PullRequestReviewID: Int64(42),
+		Position:            Int(1),
+		OriginalPosition:    Int(4),
+		CommitID:            String("ab"),
+		OriginalCommitID:    String("9c"),
+		User: &User{
+			Login:       String("ll"),
+			ID:          Int64(123),
+			AvatarURL:   String("a"),
+			GravatarID:  String("g"),
+			Name:        String("n"),
+			Company:     String("c"),
+			Blog:        String("b"),
+			Location:    String("l"),
+			Email:       String("e"),
+			Hireable:    Bool(true),
+			PublicRepos: Int(1),
+			Followers:   Int(1),
+			Following:   Int(1),
+			CreatedAt:   &Timestamp{referenceTime},
+			URL:         String("u"),
+		},
+		Reactions:      reactions,
+		CreatedAt:      &createdAt,
+		UpdatedAt:      &updatedAt,
+		URL:            String("pullrequestcommentUrl"),
+		HTMLURL:        String("pullrequestcommentHTMLUrl"),
+		PullRequestURL: String("pullrequestcommentPullRequestURL"),
+	}
+
+	want := `{
+		"id": 10,
+		"in_reply_to_id": 8,
+		"body": "Test comment",
+		"path": "file1.txt",
+		"diff_hunk": "@@ -16,33 +16,40 @@ fmt.Println()",
+		"pull_request_review_id": 42,
+		"position": 1,
+		"original_position": 4,
+		"commit_id": "ab",
+		"original_commit_id": "9c",
+		"user": {
+			"login": "ll",
+			"id": 123,
+			"avatar_url": "a",
+			"gravatar_id": "g",
+			"name": "n",
+			"company": "c",
+			"blog": "b",
+			"location": "l",
+			"email": "e",
+			"hireable": true,
+			"public_repos": 1,
+			"followers": 1,
+			"following": 1,
+			"created_at": ` + referenceTimeStr + `,
+			"url": "u"
+		},
+		"reactions": {
+			"total_count": 1,
+			"+1": 1,
+			"-1": 0,
+			"laugh": 0,
+			"confused": 0,
+			"heart": 0,
+			"hooray": 0,
+			"url": "u"
+		},
+		"created_at": "2002-02-10T15:30:00Z",
+		"updated_at": "2002-02-10T15:30:00Z",
+		"url": "pullrequestcommentUrl",
+		"html_url": "pullrequestcommentHTMLUrl",
+		"pull_request_url": "pullrequestcommentPullRequestURL"
+	}`
+
+	testJSONMarshal(t, u, want)
+}
+
 func TestPullRequestsService_ListComments_allPulls(t *testing.T) {
 	client, mux, _, teardown := setup()
 	defer teardown()
diff --git a/github/pulls_test.go b/github/pulls_test.go
index 602f03be..87e00108 100644
--- a/github/pulls_test.go
+++ b/github/pulls_test.go
@@ -275,7 +275,8 @@ func TestPullRequestsService_Create(t *testing.T) {
 		json.NewDecoder(r.Body).Decode(v)
 
 		testMethod(t, r, "POST")
-		testHeader(t, r, "Accept", mediaTypeLabelDescriptionSearchPreview)
+		wantAcceptHeaders := []string{mediaTypeLabelDescriptionSearchPreview, mediaTypeDraftPreview}
+		testHeader(t, r, "Accept", strings.Join(wantAcceptHeaders, ", "))
 		if !reflect.DeepEqual(v, input) {
 			t.Errorf("Request body = %+v, want %+v", v, input)
 		}
diff --git a/github/repos_pages_test.go b/github/repos_pages_test.go
index 21a00f9d..62d42470 100644
--- a/github/repos_pages_test.go
+++ b/github/repos_pages_test.go
@@ -10,9 +10,48 @@ import (
 	"fmt"
 	"net/http"
 	"reflect"
+	"strings"
 	"testing"
 )
 
+func TestRepositoriesService_EnablePages(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/repos/o/r/pages", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "POST")
+		wantAcceptHeaders := []string{mediaTypeEnablePagesAPIPreview, mediaTypePagesPreview}
+		testHeader(t, r, "Accept", strings.Join(wantAcceptHeaders, ", "))
+		fmt.Fprint(w, `{"url":"u","status":"s","cname":"c","custom_404":false,"html_url":"h", "source": {"branch":"master", "path":"/"}}`)
+	})
+
+	page, _, err := client.Repositories.EnablePages(context.Background(), "o", "r")
+	if err != nil {
+		t.Errorf("Repositories.EnablePages returned error: %v", err)
+	}
+
+	want := &Pages{URL: String("u"), Status: String("s"), CNAME: String("c"), Custom404: Bool(false), HTMLURL: String("h"), Source: &PagesSource{Branch: String("master"), Path: String("/")}}
+
+	if !reflect.DeepEqual(page, want) {
+		t.Errorf("Repositories.EnablePages returned %v, want %v", page, want)
+	}
+}
+
+func TestRepositoriesService_DisablePages(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/repos/o/r/pages", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "DELETE")
+		testHeader(t, r, "Accept", mediaTypeEnablePagesAPIPreview)
+	})
+
+	_, err := client.Repositories.DisablePages(context.Background(), "o", "r")
+	if err != nil {
+		t.Errorf("Repositories.DisablePages returned error: %v", err)
+	}
+}
+
 func TestRepositoriesService_GetPagesInfo(t *testing.T) {
 	client, mux, _, teardown := setup()
 	defer teardown()