Repository: google/go-github
Pull request #1188 (2019-06-09 12:38:28)

add automated-security-fixes endpoint
Adding automated-security-fixes endpoint

fixes: https://github.com/google/go-github/issues/1184

codecov[bot]: # [Codecov](https://codecov.io/gh/google/go-github/pull/1188?src=pr&el=h1) Report
> Merging [#1188](https://codecov.io/gh/google/go-github/pull/1188?src=pr&el=desc) into [master](https://codecov.io/gh/google/go-github/commit/8354c0739a78b30158359e98fe14ca3bb823159c?src=pr&el=desc) will **increase** coverage by `<.01%`.
> The diff coverage is `71.42%`.

[![Impacted file tree graph](https://codecov.io/gh/google/go-github/pull/1188/graphs/tree.svg?width=650&token=EgYjGjZlI0&height=150&src=pr)](https://codecov.io/gh/google/go-github/pull/1188?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master    #1188      +/-   ##
==========================================
+ Coverage   70.25%   70.26%   +<.01%     
==========================================
  Files          84       84              
  Lines        5867     5881      +14     
==========================================
+ Hits         4122     4132      +10     
- Misses        956      958       +2     
- Partials      789      791       +2
```


| [Impacted Files](https://codecov.io/gh/google/go-github/pull/1188?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [github/github.go](https://codecov.io/gh/google/go-github/pull/1188/diff?src=pr&el=tree#diff-Z2l0aHViL2dpdGh1Yi5nbw==) | `87.53% <ø> (ø)` | :arrow_up: |
| [github/repos.go](https://codecov.io/gh/google/go-github/pull/1188/diff?src=pr&el=tree#diff-Z2l0aHViL3JlcG9zLmdv) | `67.5% <71.42%> (+0.12%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/google/go-github/pull/1188?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/google/go-github/pull/1188?src=pr&el=footer). Last update [8354c07...b5b0b29](https://codecov.io/gh/google/go-github/pull/1188?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

gmlewis: Hi @cpanato, it looks like I don't have permission to merge the changes to your PR.  I think there is an "Allow maintainers to push to PR" or something like that if you want to try enabling it.

```
$ git push git@github.com:cpanato/go-github cpanato-GH-1184
Counting objects: 7, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (7/7), done.
Writing objects: 100% (7/7), 1.75 KiB | 596.00 KiB/s, done.
Total 7 (delta 6), reused 0 (delta 0)
remote: Resolving deltas: 100% (6/6), completed with 6 local objects.
To github.com:cpanato/go-github
 ! [remote rejected] cpanato-GH-1184 -> cpanato-GH-1184 (permission denied)
error: failed to push some refs to 'git@github.com:cpanato/go-github'
```

Otherwise, you are doing to have to resolve the conflicts yourself because the GitHub web editor doesn't appear to be working currently. Sorry about that.

The only change that's needed is to move your new custom header after the other new one:

```diff
diff --git a/github/github.go b/github/github.go
index bfe0453..d6b75ee 100644
--- a/github/github.go
+++ b/github/github.go
@@ -140,6 +140,9 @@ const (
 
        // https://developer.github.com/changes/2019-05-29-update-branch-api/
        mediaTypeUpdatePullRequestBranchPreview = "application/vnd.github.lydian-preview+json"
+
+       // https://developer.github.com/changes/2019-06-04-automated-security-fixes/
+       mediaTypeRequiredAutomatedSecurityFixesPreview = "application/vnd.github.london-preview+json"
 )
 
 // A Client manages communication with the GitHub API.
```

cpanato: @gmlewis the Allow maintainers to push to PR is checked. i will rebase :)

Patch:
diff --git a/github/apps.go b/github/apps.go
index 1ad9a981..80dfb3c8 100644
--- a/github/apps.go
+++ b/github/apps.go
@@ -26,8 +26,8 @@ type App struct {
 	Description *string    `json:"description,omitempty"`
 	ExternalURL *string    `json:"external_url,omitempty"`
 	HTMLURL     *string    `json:"html_url,omitempty"`
-	CreatedAt   *time.Time `json:"created_at,omitempty"`
-	UpdatedAt   *time.Time `json:"updated_at,omitempty"`
+	CreatedAt   *Timestamp `json:"created_at,omitempty"`
+	UpdatedAt   *Timestamp `json:"updated_at,omitempty"`
 }
 
 // InstallationToken represents an installation token.
diff --git a/github/github-accessors.go b/github/github-accessors.go
index 62fddd20..9cd33103 100644
--- a/github/github-accessors.go
+++ b/github/github-accessors.go
@@ -117,9 +117,9 @@ func (a *APIMeta) GetVerifiablePasswordAuthentication() bool {
 }
 
 // GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise.
-func (a *App) GetCreatedAt() time.Time {
+func (a *App) GetCreatedAt() Timestamp {
 	if a == nil || a.CreatedAt == nil {
-		return time.Time{}
+		return Timestamp{}
 	}
 	return *a.CreatedAt
 }
@@ -181,9 +181,9 @@ func (a *App) GetOwner() *User {
 }
 
 // GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise.
-func (a *App) GetUpdatedAt() time.Time {
+func (a *App) GetUpdatedAt() Timestamp {
 	if a == nil || a.UpdatedAt == nil {
-		return time.Time{}
+		return Timestamp{}
 	}
 	return *a.UpdatedAt
 }
@@ -484,6 +484,30 @@ func (b *Branch) GetProtected() bool {
 	return *b.Protected
 }
 
+// GetCommit returns the Commit field.
+func (b *BranchCommit) GetCommit() *Commit {
+	if b == nil {
+		return nil
+	}
+	return b.Commit
+}
+
+// GetName returns the Name field if it's non-nil, zero value otherwise.
+func (b *BranchCommit) GetName() string {
+	if b == nil || b.Name == nil {
+		return ""
+	}
+	return *b.Name
+}
+
+// GetProtected returns the Protected field if it's non-nil, zero value otherwise.
+func (b *BranchCommit) GetProtected() string {
+	if b == nil || b.Protected == nil {
+		return ""
+	}
+	return *b.Protected
+}
+
 // GetApp returns the App field.
 func (c *CheckRun) GetApp() *App {
 	if c == nil {
diff --git a/github/github.go b/github/github.go
index bfe0453e..45a72d7a 100644
--- a/github/github.go
+++ b/github/github.go
@@ -138,8 +138,14 @@ const (
 	// https://developer.github.com/changes/2019-04-24-vulnerability-alerts/
 	mediaTypeRequiredVulnerabilityAlertsPreview = "application/vnd.github.dorian-preview+json"
 
+	// https://developer.github.com/changes/2019-06-04-automated-security-fixes/
+	mediaTypeRequiredAutomatedSecurityFixesPreview = "application/vnd.github.london-preview+json"
+
 	// https://developer.github.com/changes/2019-05-29-update-branch-api/
 	mediaTypeUpdatePullRequestBranchPreview = "application/vnd.github.lydian-preview+json"
+
+	// https://developer.github.com/changes/2019-04-11-pulls-branches-for-commit/
+	mediaTypeListPullsOrBranchesForCommitPreview = "application/vnd.github.groot-preview+json"
 )
 
 // A Client manages communication with the GitHub API.
diff --git a/github/pulls.go b/github/pulls.go
index a8670f9b..a06f97bc 100644
--- a/github/pulls.go
+++ b/github/pulls.go
@@ -159,6 +159,35 @@ func (s *PullRequestsService) List(ctx context.Context, owner string, repo strin
 	return pulls, resp, nil
 }
 
+// ListPullRequestsWithCommit returns pull requests associated with a commit SHA.
+//
+// The results will include open and closed pull requests.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/commits/#list-pull-requests-associated-with-commit
+func (s *PullRequestsService) ListPullRequestsWithCommit(ctx context.Context, owner, repo, sha string, opt *PullRequestListOptions) ([]*PullRequest, *Response, error) {
+	u := fmt.Sprintf("repos/%v/%v/commits/%v/pulls", owner, repo, sha)
+	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
+	}
+
+	// TODO: remove custom Accept header when this API fully launches.
+	acceptHeaders := []string{mediaTypeListPullsOrBranchesForCommitPreview, mediaTypeDraftPreview, mediaTypeLabelDescriptionSearchPreview, mediaTypeLockReasonPreview}
+	req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
+	var pulls []*PullRequest
+	resp, err := s.client.Do(ctx, req, &pulls)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return pulls, resp, nil
+}
+
 // Get a single pull request.
 //
 // GitHub API docs: https://developer.github.com/v3/pulls/#get-a-single-pull-request
diff --git a/github/repos.go b/github/repos.go
index 154d28bb..5f44c6d8 100644
--- a/github/repos.go
+++ b/github/repos.go
@@ -496,6 +496,40 @@ func (s *RepositoriesService) DisableVulnerabilityAlerts(ctx context.Context, ow
 	return s.client.Do(ctx, req, nil)
 }
 
+// EnableAutomatedSecurityFixes enables the automated security fixes for a repository.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/#enable-automated-security-fixes
+func (s *RepositoriesService) EnableAutomatedSecurityFixes(ctx context.Context, owner, repository string) (*Response, error) {
+	u := fmt.Sprintf("repos/%v/%v/automated-security-fixes", owner, repository)
+
+	req, err := s.client.NewRequest("PUT", u, nil)
+	if err != nil {
+		return nil, err
+	}
+
+	// TODO: remove custom Accept header when this API fully launches
+	req.Header.Set("Accept", mediaTypeRequiredAutomatedSecurityFixesPreview)
+
+	return s.client.Do(ctx, req, nil)
+}
+
+// DisableAutomatedSecurityFixes disables vulnerability alerts and the dependency graph for a repository.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/#disable-automated-security-fixes
+func (s *RepositoriesService) DisableAutomatedSecurityFixes(ctx context.Context, owner, repository string) (*Response, error) {
+	u := fmt.Sprintf("repos/%v/%v/automated-security-fixes", owner, repository)
+
+	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", mediaTypeRequiredAutomatedSecurityFixesPreview)
+
+	return s.client.Do(ctx, req, nil)
+}
+
 // ListContributors lists contributors for a repository.
 //
 // GitHub API docs: https://developer.github.com/v3/repos/#list-contributors
diff --git a/github/repos_commits.go b/github/repos_commits.go
index 83cdf5b3..95096923 100644
--- a/github/repos_commits.go
+++ b/github/repos_commits.go
@@ -115,6 +115,13 @@ type CommitsListOptions struct {
 	ListOptions
 }
 
+// BranchCommit is the result of listing branches with commit SHA.
+type BranchCommit struct {
+	Name      *string `json:"name,omitempty"`
+	Commit    *Commit `json:"commit,omitempty"`
+	Protected *string `json:"protected,omitempty"`
+}
+
 // ListCommits lists the commits of a repository.
 //
 // GitHub API docs: https://developer.github.com/v3/repos/commits/#list
@@ -232,3 +239,26 @@ func (s *RepositoriesService) CompareCommits(ctx context.Context, owner, repo st
 
 	return comp, resp, nil
 }
+
+// ListBranchesHeadCommit gets all branches where the given commit SHA is the HEAD,
+// or latest commit for the branch.
+//
+// GitHub API docs: https://developer.github.com/v3/repos/commits/#list-branches-for-head-commit
+func (s *RepositoriesService) ListBranchesHeadCommit(ctx context.Context, owner, repo, sha string) ([]*BranchCommit, *Response, error) {
+	u := fmt.Sprintf("repos/%v/%v/commits/%v/branches-where-head", owner, repo, sha)
+
+	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", mediaTypeListPullsOrBranchesForCommitPreview)
+	var branchCommits []*BranchCommit
+	resp, err := s.client.Do(ctx, req, &branchCommits)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return branchCommits, resp, nil
+}


Test patch:
diff --git a/github/pulls_test.go b/github/pulls_test.go
index ba45b6fd..09d60e3a 100644
--- a/github/pulls_test.go
+++ b/github/pulls_test.go
@@ -47,6 +47,37 @@ func TestPullRequestsService_List(t *testing.T) {
 	}
 }
 
+func TestPullRequestsService_ListPullRequestsWithCommit(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	wantAcceptHeaders := []string{mediaTypeListPullsOrBranchesForCommitPreview, mediaTypeDraftPreview, mediaTypeLabelDescriptionSearchPreview, mediaTypeLockReasonPreview}
+	mux.HandleFunc("/repos/o/r/commits/sha/pulls", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "GET")
+		testHeader(t, r, "Accept", strings.Join(wantAcceptHeaders, ", "))
+		testFormValues(t, r, values{
+			"state":     "closed",
+			"head":      "h",
+			"base":      "b",
+			"sort":      "created",
+			"direction": "desc",
+			"page":      "2",
+		})
+		fmt.Fprint(w, `[{"number":1}]`)
+	})
+
+	opt := &PullRequestListOptions{"closed", "h", "b", "created", "desc", ListOptions{Page: 2}}
+	pulls, _, err := client.PullRequests.ListPullRequestsWithCommit(context.Background(), "o", "r", "sha", opt)
+	if err != nil {
+		t.Errorf("PullRequests.ListPullRequestsWithCommit returned error: %v", err)
+	}
+
+	want := []*PullRequest{{Number: Int(1)}}
+	if !reflect.DeepEqual(pulls, want) {
+		t.Errorf("PullRequests.ListPullRequestsWithCommit returned %+v, want %+v", pulls, want)
+	}
+}
+
 func TestPullRequestsService_List_invalidOwner(t *testing.T) {
 	client, _, _, teardown := setup()
 	defer teardown()
diff --git a/github/repos_commits_test.go b/github/repos_commits_test.go
index e076febb..feed2b95 100644
--- a/github/repos_commits_test.go
+++ b/github/repos_commits_test.go
@@ -360,3 +360,23 @@ func TestRepositoriesService_CompareCommits(t *testing.T) {
 		t.Errorf("Repositories.CompareCommits returned \n%+v, want \n%+v", got, want)
 	}
 }
+
+func TestRepositoriesService_ListBranchesHeadCommit(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/repos/o/r/commits/s/branches-where-head", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "GET")
+		fmt.Fprintf(w, `[{"name": "b"}]`)
+	})
+
+	branches, _, err := client.Repositories.ListBranchesHeadCommit(context.Background(), "o", "r", "s")
+	if err != nil {
+		t.Errorf("Repositories.ListBranchesHeadCommit returned error: %v", err)
+	}
+
+	want := []*BranchCommit{{Name: String("b")}}
+	if !reflect.DeepEqual(branches, want) {
+		t.Errorf("Repositories.ListBranchesHeadCommit returned %+v, want %+v", branches, want)
+	}
+}
diff --git a/github/repos_test.go b/github/repos_test.go
index cb91a386..6dd9973c 100644
--- a/github/repos_test.go
+++ b/github/repos_test.go
@@ -399,6 +399,38 @@ func TestRepositoriesService_DisableVulnerabilityAlerts(t *testing.T) {
 	}
 }
 
+func TestRepositoriesService_EnableAutomatedSecurityFixes(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/repos/o/r/automated-security-fixes", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "PUT")
+		testHeader(t, r, "Accept", mediaTypeRequiredAutomatedSecurityFixesPreview)
+
+		w.WriteHeader(http.StatusNoContent)
+	})
+
+	if _, err := client.Repositories.EnableAutomatedSecurityFixes(context.Background(), "o", "r"); err != nil {
+		t.Errorf("Repositories.EnableAutomatedSecurityFixes returned error: %v", err)
+	}
+}
+
+func TestRepositoriesService_DisableAutomatedSecurityFixes(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/repos/o/r/automated-security-fixes", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "DELETE")
+		testHeader(t, r, "Accept", mediaTypeRequiredAutomatedSecurityFixesPreview)
+
+		w.WriteHeader(http.StatusNoContent)
+	})
+
+	if _, err := client.Repositories.DisableAutomatedSecurityFixes(context.Background(), "o", "r"); err != nil {
+		t.Errorf("Repositories.DisableAutomatedSecurityFixes returned error: %v", err)
+	}
+}
+
 func TestRepositoriesService_ListContributors(t *testing.T) {
 	client, mux, _, teardown := setup()
 	defer teardown()