Repository: google/go-github (go)

Issue:
Support preview Update Branch API
GitHub Developer API announcement:
https://developer.github.com/changes/2019-05-29-update-branch-api/

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 description:
Added update branch API
Fixes #1183

Patch:
diff --git a/github/github-accessors.go b/github/github-accessors.go
index 9129909a..62fddd20 100644
--- a/github/github-accessors.go
+++ b/github/github-accessors.go
@@ -7228,6 +7228,14 @@ func (p *PublicEvent) GetSender() *User {
 	return p.Sender
 }
 
+// GetExpectedHeadSHA returns the ExpectedHeadSHA field if it's non-nil, zero value otherwise.
+func (p *PullReqestBranchUpdateOptions) GetExpectedHeadSHA() string {
+	if p == nil || p.ExpectedHeadSHA == nil {
+		return ""
+	}
+	return *p.ExpectedHeadSHA
+}
+
 // GetActiveLockReason returns the ActiveLockReason field if it's non-nil, zero value otherwise.
 func (p *PullRequest) GetActiveLockReason() string {
 	if p == nil || p.ActiveLockReason == nil {
@@ -7596,6 +7604,22 @@ func (p *PullRequestBranch) GetUser() *User {
 	return p.User
 }
 
+// GetMessage returns the Message field if it's non-nil, zero value otherwise.
+func (p *PullRequestBranchUpdateResponse) GetMessage() string {
+	if p == nil || p.Message == nil {
+		return ""
+	}
+	return *p.Message
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (p *PullRequestBranchUpdateResponse) GetURL() string {
+	if p == nil || p.URL == nil {
+		return ""
+	}
+	return *p.URL
+}
+
 // GetAuthorAssociation returns the AuthorAssociation field if it's non-nil, zero value otherwise.
 func (p *PullRequestComment) GetAuthorAssociation() string {
 	if p == nil || p.AuthorAssociation == nil {
diff --git a/github/github.go b/github/github.go
index 6bef3a64..bfe0453e 100644
--- a/github/github.go
+++ b/github/github.go
@@ -137,6 +137,9 @@ const (
 
 	// https://developer.github.com/changes/2019-04-24-vulnerability-alerts/
 	mediaTypeRequiredVulnerabilityAlertsPreview = "application/vnd.github.dorian-preview+json"
+
+	// https://developer.github.com/changes/2019-05-29-update-branch-api/
+	mediaTypeUpdatePullRequestBranchPreview = "application/vnd.github.lydian-preview+json"
 )
 
 // A Client manages communication with the GitHub API.
diff --git a/github/pulls.go b/github/pulls.go
index b26f6c5c..a8670f9b 100644
--- a/github/pulls.go
+++ b/github/pulls.go
@@ -242,6 +242,49 @@ func (s *PullRequestsService) Create(ctx context.Context, owner string, repo str
 	return p, resp, nil
 }
 
+// PullReqestBranchUpdateOptions specifies the optional parameters to the
+// PullRequestsService.UpdateBranch method.
+type PullReqestBranchUpdateOptions struct {
+	// ExpectedHeadSHA specifies the most recent commit on the pull request's branch.
+	// Default value is the SHA of the pull request's current HEAD ref.
+	ExpectedHeadSHA *string `json:"expected_head_sha,omitempty"`
+}
+
+// PullRequestBranchUpdateResponse specifies the response of pull request branch update.
+type PullRequestBranchUpdateResponse struct {
+	Message *string `json:"message,omitempty"`
+	URL     *string `json:"url,omitempty"`
+}
+
+// UpdateBranch updates the pull request branch with latest upstream changes.
+//
+// This method might return an AcceptedError and a status code of
+// 202. This is because this is the status that GitHub returns to signify that
+// it has now scheduled the update of the pull request branch in a background task.
+// A follow up request, after a delay of a second or so, should result
+// in a successful request.
+//
+// GitHub API docs: https://developer.github.com/v3/pulls/#update-a-pull-request-branch
+func (s *PullRequestsService) UpdateBranch(ctx context.Context, owner, repo string, number int, opts *PullReqestBranchUpdateOptions) (*PullRequestBranchUpdateResponse, *Response, error) {
+	u := fmt.Sprintf("repos/%v/%v/pulls/%d/update-branch", owner, repo, number)
+
+	req, err := s.client.NewRequest("PUT", u, opts)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	// TODO: remove custom Accept header when this API fully launches.
+	req.Header.Set("Accept", mediaTypeUpdatePullRequestBranchPreview)
+
+	p := new(PullRequestBranchUpdateResponse)
+	resp, err := s.client.Do(ctx, req, p)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return p, resp, nil
+}
+
 type pullRequestUpdate struct {
 	Title               *string `json:"title,omitempty"`
 	Body                *string `json:"body,omitempty"`


Test patch:
diff --git a/github/pulls_test.go b/github/pulls_test.go
index 87e00108..ba45b6fd 100644
--- a/github/pulls_test.go
+++ b/github/pulls_test.go
@@ -303,6 +303,39 @@ func TestPullRequestsService_Create_invalidOwner(t *testing.T) {
 	testURLParseError(t, err)
 }
 
+func TestPullRequestsService_UpdateBranch(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/repos/o/r/pulls/1/update-branch", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "PUT")
+		testHeader(t, r, "Accept", mediaTypeUpdatePullRequestBranchPreview)
+		fmt.Fprint(w, `
+			{
+			  "message": "Updating pull request branch.",
+			  "url": "https://github.com/repos/o/r/pulls/1"
+			}`)
+	})
+
+	opts := &PullReqestBranchUpdateOptions{
+		ExpectedHeadSHA: String("s"),
+	}
+
+	pull, _, err := client.PullRequests.UpdateBranch(context.Background(), "o", "r", 1, opts)
+	if err != nil {
+		t.Errorf("PullRequests.UpdateBranch returned error: %v", err)
+	}
+
+	want := &PullRequestBranchUpdateResponse{
+		Message: String("Updating pull request branch."),
+		URL:     String("https://github.com/repos/o/r/pulls/1"),
+	}
+
+	if !reflect.DeepEqual(pull, want) {
+		t.Errorf("PullRequests.UpdateBranch returned %+v, want %+v", pull, want)
+	}
+}
+
 func TestPullRequestsService_Edit(t *testing.T) {
 	client, mux, _, teardown := setup()
 	defer teardown()