Repository: google/go-github (go)

Issue:
Support pagination for ListEnvironments
Hey,

Would you consider supporting pagination for the ListEnvironments method? I appreciate that it is probably an edge case request but it would be nice to be able to pass in opts to the request for pagination in the instance where you have a lot of environments.


`func (s *RepositoriesService) ListEnvironments(ctx context.Context, owner, repo string, opts *ListOptions)`

Pull request:
Add list options support for environments
Closes #2257 

This PR introduces an EnvironmentListOptions parameter for the ListEnvironments method.

Tests have also been updated to reflect the changes and an example has been added to the example directory.

Patch:
diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml
index 5f35fac3..5a3f8dd5 100644
--- a/.github/workflows/linter.yml
+++ b/.github/workflows/linter.yml
@@ -15,5 +15,5 @@ jobs:
     - name: golangci-lint
       uses: golangci/golangci-lint-action@5c56cd6c9dc07901af25baab6f2b0d9f3b7c3018 #v2.5.2
       with:
-        version: v1.41
+        version: v1.44.0
         args: --verbose
diff --git a/example/listenvironments/main.go b/example/listenvironments/main.go
new file mode 100644
index 00000000..11f9d802
--- /dev/null
+++ b/example/listenvironments/main.go
@@ -0,0 +1,53 @@
+// Copyright 2022 The go-github AUTHORS. All rights reserved.
+//
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// listenvironments is an example of how to use ListEnvironments method with EnvironmentListOptions.
+// It's runnable with the following command:
+// 		export GITHUB_TOKEN=your_token
+//		export GITHUB_REPOSITORY_OWNER=your_owner
+//		export GITHUB_REPOSITORY_NAME=your_repo
+//		go run .
+package main
+
+import (
+	"context"
+	"fmt"
+	"log"
+	"os"
+
+	"github.com/google/go-github/v42/github"
+	"golang.org/x/oauth2"
+)
+
+func main() {
+	token := os.Getenv("GITHUB_AUTH_TOKEN")
+	repo := os.Getenv("GITHUB_REPOSITORY_NAME")
+	owner := os.Getenv("GITHUB_REPOSITORY_OWNER")
+
+	if token == "" {
+		log.Fatal("Unauthorized: No token present")
+	}
+
+	ts := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: token})
+
+	ctx := context.Background()
+	tc := oauth2.NewClient(ctx, ts)
+	client := github.NewClient(tc)
+
+	expectedPageSize := 2
+
+	opts := &github.EnvironmentListOptions{ListOptions: github.ListOptions{PerPage: expectedPageSize}}
+	envResponse, _, err := client.Repositories.ListEnvironments(ctx, owner, repo, opts)
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	if len(envResponse.Environments) != expectedPageSize {
+		log.Fatal("Unexpected number of environments returned")
+	}
+
+	// The number of environments here should be equal to expectedPageSize
+	fmt.Printf("%d environments returned\n", len(envResponse.Environments))
+}
diff --git a/github/actions_workflows.go b/github/actions_workflows.go
index 3ce926fe..e0568462 100644
--- a/github/actions_workflows.go
+++ b/github/actions_workflows.go
@@ -50,7 +50,7 @@ type WorkflowBill struct {
 // CreateWorkflowDispatchEventRequest represents a request to create a workflow dispatch event.
 type CreateWorkflowDispatchEventRequest struct {
 	// Ref represents the reference of the workflow run.
-	// The reference can be a branch, tag, or a commit SHA.
+	// The reference can be a branch or a tag.
 	// Ref is required when creating a workflow dispatch event.
 	Ref string `json:"ref"`
 	// Inputs represents input keys and values configured in the workflow file.
diff --git a/github/event_types.go b/github/event_types.go
index 6a806c4a..c2382883 100644
--- a/github/event_types.go
+++ b/github/event_types.go
@@ -145,7 +145,15 @@ type DeployKeyEvent struct {
 	// The deploy key resource.
 	Key *Key `json:"key,omitempty"`
 
+	// The Repository where the event occurred
+	Repo *Repository `json:"repository,omitempty"`
+
+	// The following field is only present when the webhook is triggered on
+	// a repository belonging to an organization.
+	Organization *Organization `json:"organization,omitempty"`
+
 	// The following fields are only populated by Webhook events.
+	Sender       *User         `json:"sender,omitempty"`
 	Installation *Installation `json:"installation,omitempty"`
 }
 
diff --git a/github/github-accessors.go b/github/github-accessors.go
index 059a285a..4bc74e57 100644
--- a/github/github-accessors.go
+++ b/github/github-accessors.go
@@ -3444,6 +3444,30 @@ func (d *DeployKeyEvent) GetKey() *Key {
 	return d.Key
 }
 
+// GetOrganization returns the Organization field.
+func (d *DeployKeyEvent) GetOrganization() *Organization {
+	if d == nil {
+		return nil
+	}
+	return d.Organization
+}
+
+// GetRepo returns the Repo field.
+func (d *DeployKeyEvent) GetRepo() *Repository {
+	if d == nil {
+		return nil
+	}
+	return d.Repo
+}
+
+// GetSender returns the Sender field.
+func (d *DeployKeyEvent) GetSender() *User {
+	if d == nil {
+		return nil
+	}
+	return d.Sender
+}
+
 // GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise.
 func (d *Deployment) GetCreatedAt() Timestamp {
 	if d == nil || d.CreatedAt == nil {
@@ -10484,6 +10508,22 @@ func (p *PagesUpdate) GetCNAME() string {
 	return *p.CNAME
 }
 
+// GetHTTPSEnforced returns the HTTPSEnforced field if it's non-nil, zero value otherwise.
+func (p *PagesUpdate) GetHTTPSEnforced() bool {
+	if p == nil || p.HTTPSEnforced == nil {
+		return false
+	}
+	return *p.HTTPSEnforced
+}
+
+// GetPublic returns the Public field if it's non-nil, zero value otherwise.
+func (p *PagesUpdate) GetPublic() bool {
+	if p == nil || p.Public == nil {
+		return false
+	}
+	return *p.Public
+}
+
 // GetSource returns the Source field if it's non-nil, zero value otherwise.
 func (p *PagesUpdate) GetSource() string {
 	if p == nil || p.Source == nil {
@@ -15428,6 +15468,14 @@ func (r *RequiredReviewer) GetType() string {
 	return *r.Type
 }
 
+// GetAppID returns the AppID field if it's non-nil, zero value otherwise.
+func (r *RequiredStatusCheck) GetAppID() int64 {
+	if r == nil || r.AppID == nil {
+		return 0
+	}
+	return *r.AppID
+}
+
 // GetStrict returns the Strict field if it's non-nil, zero value otherwise.
 func (r *RequiredStatusChecksRequest) GetStrict() bool {
 	if r == nil || r.Strict == nil {
diff --git a/github/repos.go b/github/repos.go
index a1c8c810..42cd1636 100644
--- a/github/repos.go
+++ b/github/repos.go
@@ -877,14 +877,33 @@ type RequiredStatusChecks struct {
 	// Require branches to be up to date before merging. (Required.)
 	Strict bool `json:"strict"`
 	// The list of status checks to require in order to merge into this
-	// branch. (Required; use []string{} instead of nil for empty list.)
-	Contexts []string `json:"contexts"`
+	// branch. (Deprecated. Note: only one of Contexts/Checks can be populated,
+	// but at least one must be populated).
+	Contexts []string `json:"contexts,omitempty"`
+	// The list of status checks to require in order to merge into this
+	// branch.
+	Checks []*RequiredStatusCheck `json:"checks,omitempty"`
 }
 
 // RequiredStatusChecksRequest represents a request to edit a protected branch's status checks.
 type RequiredStatusChecksRequest struct {
-	Strict   *bool    `json:"strict,omitempty"`
-	Contexts []string `json:"contexts,omitempty"`
+	Strict *bool `json:"strict,omitempty"`
+	// Note: if both Contexts and Checks are populated,
+	// the GitHub API will only use Checks.
+	Contexts []string               `json:"contexts,omitempty"`
+	Checks   []*RequiredStatusCheck `json:"checks,omitempty"`
+}
+
+// RequiredStatusCheck represents a status check of a protected branch.
+type RequiredStatusCheck struct {
+	// The name of the required check.
+	Context string `json:"context"`
+	// The ID of the GitHub App that must provide this check.
+	// Omit this field to automatically select the GitHub App
+	// that has recently provided this check,
+	// or any app if it was not set by a GitHub App.
+	// Pass -1 to explicitly allow any app to set the status.
+	AppID *int64 `json:"app_id,omitempty"`
 }
 
 // PullRequestReviewsEnforcement represents the pull request reviews enforcement of a protected branch.
diff --git a/github/repos_environments.go b/github/repos_environments.go
index 25cb005e..5dd45428 100644
--- a/github/repos_environments.go
+++ b/github/repos_environments.go
@@ -63,6 +63,12 @@ type RequiredReviewer struct {
 	Reviewer interface{} `json:"reviewer,omitempty"`
 }
 
+// EnvironmentListOptions specifies the optional parameters to the
+// RepositoriesService.ListEnvironments method.
+type EnvironmentListOptions struct {
+	ListOptions
+}
+
 // UnmarshalJSON implements the json.Unmarshaler interface.
 // This helps us handle the fact that RequiredReviewer can have either a User or Team type reviewer field.
 func (r *RequiredReviewer) UnmarshalJSON(data []byte) error {
@@ -99,8 +105,12 @@ func (r *RequiredReviewer) UnmarshalJSON(data []byte) error {
 // ListEnvironments lists all environments for a repository.
 //
 // GitHub API docs: https://docs.github.com/en/rest/reference/repos#get-all-environments
-func (s *RepositoriesService) ListEnvironments(ctx context.Context, owner, repo string) (*EnvResponse, *Response, error) {
+func (s *RepositoriesService) ListEnvironments(ctx context.Context, owner, repo string, opts *EnvironmentListOptions) (*EnvResponse, *Response, error) {
 	u := fmt.Sprintf("repos/%s/%s/environments", owner, repo)
+	u, err := addOptions(u, opts)
+	if err != nil {
+		return nil, nil, err
+	}
 
 	req, err := s.client.NewRequest("GET", u, nil)
 	if err != nil {
diff --git a/github/repos_pages.go b/github/repos_pages.go
index 04825bae..60a756b6 100644
--- a/github/repos_pages.go
+++ b/github/repos_pages.go
@@ -95,6 +95,13 @@ type PagesUpdate struct {
 	// Source must include the branch name, and may optionally specify the subdirectory "/docs".
 	// Possible values are: "gh-pages", "master", and "master /docs".
 	Source *string `json:"source,omitempty"`
+	// Public configures access controls for the site.
+	// If "true", the site will be accessible to anyone on the internet. If "false",
+	// the site will be accessible to anyone with read access to the repository that
+	// published the site.
+	Public *bool `json:"public,omitempty"`
+	// HTTPSEnforced specifies whether HTTPS should be enforced for the repository.
+	HTTPSEnforced *bool `json:"https_enforced,omitempty"`
 }
 
 // UpdatePages updates GitHub Pages for the named repo.
diff --git a/go.mod b/go.mod
index 4993e8d4..ca2c25f6 100644
--- a/go.mod
+++ b/go.mod
@@ -1,8 +1,8 @@
 module github.com/google/go-github/v42
 
 require (
-	github.com/bradleyfalzon/ghinstallation/v2 v2.0.3
-	github.com/google/go-cmp v0.5.6
+	github.com/bradleyfalzon/ghinstallation/v2 v2.0.4
+	github.com/google/go-cmp v0.5.7
 	github.com/google/go-querystring v1.1.0
 	golang.org/x/crypto v0.0.0-20210817164053-32db794688a5
 	golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be
@@ -12,7 +12,7 @@ require (
 require (
 	github.com/golang-jwt/jwt/v4 v4.0.0 // indirect
 	github.com/golang/protobuf v1.3.2 // indirect
-	github.com/google/go-github/v39 v39.0.0 // indirect
+	github.com/google/go-github/v41 v41.0.0 // indirect
 	golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 // indirect
 	golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 // indirect
 	golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 // indirect
diff --git a/go.sum b/go.sum
index 95ca91e2..5b69389a 100644
--- a/go.sum
+++ b/go.sum
@@ -1,15 +1,16 @@
-github.com/bradleyfalzon/ghinstallation/v2 v2.0.3 h1:ywF/8q+GVpvlsEuvRb1SGSDQDUxntW1d4kFu/9q/YAE=
-github.com/bradleyfalzon/ghinstallation/v2 v2.0.3/go.mod h1:tlgi+JWCXnKFx/Y4WtnDbZEINo31N5bcvnCoqieefmk=
+github.com/bradleyfalzon/ghinstallation/v2 v2.0.4 h1:tXKVfhE7FcSkhkv0UwkLvPDeZ4kz6OXd0PKPlFqf81M=
+github.com/bradleyfalzon/ghinstallation/v2 v2.0.4/go.mod h1:B40qPqJxWE0jDZgOR1JmaMy+4AY1eBP+IByOvqyAKp0=
 github.com/golang-jwt/jwt/v4 v4.0.0 h1:RAqyYixv1p7uEnocuy8P1nru5wprCh/MH2BIlW5z5/o=
 github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
 github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
 github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
 github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-github/v39 v39.0.0 h1:pygGA5ySwxEez1N39GnDauD0PaWWuGgayudyZAc941s=
-github.com/google/go-github/v39 v39.0.0/go.mod h1:C1s8C5aCC9L+JXIYpJM5GYytdX52vC1bLvHEF1IhBrE=
+github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
+github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
+github.com/google/go-github/v41 v41.0.0 h1:HseJrM2JFf2vfiZJ8anY2hqBjdfY1Vlj/K27ueww4gg=
+github.com/google/go-github/v41 v41.0.0/go.mod h1:XgmCA5H323A9rtgExdTcnDkcqp6S30AVACCBDOonIxg=
 github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
 github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
diff --git a/scrape/go.mod b/scrape/go.mod
index 35e51cc8..a0ab873e 100644
--- a/scrape/go.mod
+++ b/scrape/go.mod
@@ -4,7 +4,7 @@ go 1.13
 
 require (
 	github.com/PuerkitoBio/goquery v1.8.0
-	github.com/google/go-cmp v0.5.6
+	github.com/google/go-cmp v0.5.7
 	github.com/google/go-github/v42 v42.0.0
 	github.com/xlzd/gotp v0.0.0-20181030022105-c8557ba2c119
 	golang.org/x/net v0.0.0-20210916014120-12bc252f5db8
diff --git a/scrape/go.sum b/scrape/go.sum
index 062a653f..4cbca57c 100644
--- a/scrape/go.sum
+++ b/scrape/go.sum
@@ -7,8 +7,9 @@ github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzw
 github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
 github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
+github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
 github.com/google/go-github/v39 v39.0.0/go.mod h1:C1s8C5aCC9L+JXIYpJM5GYytdX52vC1bLvHEF1IhBrE=
 github.com/google/go-github/v42 v42.0.0 h1:YNT0FwjPrEysRkLIiKuEfSvBPCGKphW5aS5PxwaoLec=
 github.com/google/go-github/v42 v42.0.0/go.mod h1:jgg/jvyI0YlDOM1/ps6XYh04HNQ3vKf0CVko62/EhRg=
diff --git a/update-urls/go.mod b/update-urls/go.mod
index 53666db8..2cb2ce32 100644
--- a/update-urls/go.mod
+++ b/update-urls/go.mod
@@ -3,6 +3,6 @@ module github.com/google/go-github/update-urls
 go 1.16
 
 require (
-	github.com/google/go-cmp v0.5.6
+	github.com/google/go-cmp v0.5.7
 	github.com/pmezard/go-difflib v1.0.0
 )
diff --git a/update-urls/go.sum b/update-urls/go.sum
index cbfdfa22..a91bb23c 100644
--- a/update-urls/go.sum
+++ b/update-urls/go.sum
@@ -1,5 +1,5 @@
-github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
-github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
+github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=


Test patch:
diff --git a/github/event_types_test.go b/github/event_types_test.go
index 221d20c5..67cc1171 100644
--- a/github/event_types_test.go
+++ b/github/event_types_test.go
@@ -10220,6 +10220,42 @@ func TestDeployKeyEvent_Marshal(t *testing.T) {
 			Verified:  Bool(false),
 			CreatedAt: &Timestamp{referenceTime},
 		},
+		Repo: &Repository{
+			ID:   Int64(1),
+			URL:  String("s"),
+			Name: String("n"),
+		},
+		Organization: &Organization{
+			BillingEmail:                         String("be"),
+			Blog:                                 String("b"),
+			Company:                              String("c"),
+			Email:                                String("e"),
+			TwitterUsername:                      String("tu"),
+			Location:                             String("loc"),
+			Name:                                 String("n"),
+			Description:                          String("d"),
+			IsVerified:                           Bool(true),
+			HasOrganizationProjects:              Bool(true),
+			HasRepositoryProjects:                Bool(true),
+			DefaultRepoPermission:                String("drp"),
+			MembersCanCreateRepos:                Bool(true),
+			MembersCanCreateInternalRepos:        Bool(true),
+			MembersCanCreatePrivateRepos:         Bool(true),
+			MembersCanCreatePublicRepos:          Bool(false),
+			MembersAllowedRepositoryCreationType: String("marct"),
+			MembersCanCreatePages:                Bool(true),
+			MembersCanCreatePublicPages:          Bool(false),
+			MembersCanCreatePrivatePages:         Bool(true),
+		},
+		Sender: &User{
+			Login:     String("l"),
+			ID:        Int64(1),
+			NodeID:    String("n"),
+			AvatarURL: String("a"),
+			URL:       String("u"),
+			EventsURL: String("e"),
+			ReposURL:  String("r"),
+		},
 	}
 
 	want := `{
@@ -10232,6 +10268,42 @@ func TestDeployKeyEvent_Marshal(t *testing.T) {
 			"read_only": false,
 			"verified": false,
 			"created_at": ` + referenceTimeStr + `
+		},
+		"repository": {
+			"id": 1,
+			"name": "n",
+			"url": "s"
+		},
+		"organization": {
+			"name": "n",
+			"company": "c",
+			"blog": "b",
+			"location": "loc",
+			"email": "e",
+			"twitter_username": "tu",
+			"description": "d",
+			"billing_email": "be",
+			"is_verified": true,
+			"has_organization_projects": true,
+			"has_repository_projects": true,
+			"default_repository_permission": "drp",
+			"members_can_create_repositories": true,
+			"members_can_create_public_repositories": false,
+			"members_can_create_private_repositories": true,
+			"members_can_create_internal_repositories": true,
+			"members_allowed_repository_creation_type": "marct",
+			"members_can_create_pages": true,
+			"members_can_create_public_pages": false,
+			"members_can_create_private_pages": true
+		},
+		"sender": {
+			"login": "l",
+			"id": 1,
+			"node_id": "n",
+			"avatar_url": "a",
+			"url": "u",
+			"events_url": "e",
+			"repos_url": "r"
 		}
 	}`
 
diff --git a/github/github-accessors_test.go b/github/github-accessors_test.go
index c36432a7..3c480f4e 100644
--- a/github/github-accessors_test.go
+++ b/github/github-accessors_test.go
@@ -4027,6 +4027,27 @@ func TestDeployKeyEvent_GetKey(tt *testing.T) {
 	d.GetKey()
 }
 
+func TestDeployKeyEvent_GetOrganization(tt *testing.T) {
+	d := &DeployKeyEvent{}
+	d.GetOrganization()
+	d = nil
+	d.GetOrganization()
+}
+
+func TestDeployKeyEvent_GetRepo(tt *testing.T) {
+	d := &DeployKeyEvent{}
+	d.GetRepo()
+	d = nil
+	d.GetRepo()
+}
+
+func TestDeployKeyEvent_GetSender(tt *testing.T) {
+	d := &DeployKeyEvent{}
+	d.GetSender()
+	d = nil
+	d.GetSender()
+}
+
 func TestDeployment_GetCreatedAt(tt *testing.T) {
 	var zeroValue Timestamp
 	d := &Deployment{CreatedAt: &zeroValue}
@@ -12305,6 +12326,26 @@ func TestPagesUpdate_GetCNAME(tt *testing.T) {
 	p.GetCNAME()
 }
 
+func TestPagesUpdate_GetHTTPSEnforced(tt *testing.T) {
+	var zeroValue bool
+	p := &PagesUpdate{HTTPSEnforced: &zeroValue}
+	p.GetHTTPSEnforced()
+	p = &PagesUpdate{}
+	p.GetHTTPSEnforced()
+	p = nil
+	p.GetHTTPSEnforced()
+}
+
+func TestPagesUpdate_GetPublic(tt *testing.T) {
+	var zeroValue bool
+	p := &PagesUpdate{Public: &zeroValue}
+	p.GetPublic()
+	p = &PagesUpdate{}
+	p.GetPublic()
+	p = nil
+	p.GetPublic()
+}
+
 func TestPagesUpdate_GetSource(tt *testing.T) {
 	var zeroValue string
 	p := &PagesUpdate{Source: &zeroValue}
@@ -18023,6 +18064,16 @@ func TestRequiredReviewer_GetType(tt *testing.T) {
 	r.GetType()
 }
 
+func TestRequiredStatusCheck_GetAppID(tt *testing.T) {
+	var zeroValue int64
+	r := &RequiredStatusCheck{AppID: &zeroValue}
+	r.GetAppID()
+	r = &RequiredStatusCheck{}
+	r.GetAppID()
+	r = nil
+	r.GetAppID()
+}
+
 func TestRequiredStatusChecksRequest_GetStrict(tt *testing.T) {
 	var zeroValue bool
 	r := &RequiredStatusChecksRequest{Strict: &zeroValue}
diff --git a/github/repos_environments_test.go b/github/repos_environments_test.go
index 18a30ad6..59b3f8b4 100644
--- a/github/repos_environments_test.go
+++ b/github/repos_environments_test.go
@@ -108,8 +108,14 @@ func TestRepositoriesService_ListEnvironments(t *testing.T) {
 		fmt.Fprint(w, `{"total_count":1, "environments":[{"id":1}, {"id": 2}]}`)
 	})
 
+	opt := &EnvironmentListOptions{
+		ListOptions: ListOptions{
+			Page:    2,
+			PerPage: 2,
+		},
+	}
 	ctx := context.Background()
-	environments, _, err := client.Repositories.ListEnvironments(ctx, "o", "r")
+	environments, _, err := client.Repositories.ListEnvironments(ctx, "o", "r", opt)
 	if err != nil {
 		t.Errorf("Repositories.ListEnvironments returned error: %v", err)
 	}
@@ -120,12 +126,12 @@ func TestRepositoriesService_ListEnvironments(t *testing.T) {
 
 	const methodName = "ListEnvironments"
 	testBadOptions(t, methodName, func() (err error) {
-		_, _, err = client.Repositories.ListEnvironments(ctx, "\n", "\n")
+		_, _, err = client.Repositories.ListEnvironments(ctx, "\n", "\n", opt)
 		return err
 	})
 
 	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
-		got, resp, err := client.Repositories.ListEnvironments(ctx, "o", "r")
+		got, resp, err := client.Repositories.ListEnvironments(ctx, "o", "r", opt)
 		if got != nil {
 			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
 		}
diff --git a/github/repos_test.go b/github/repos_test.go
index 58c8aab5..5739c10b 100644
--- a/github/repos_test.go
+++ b/github/repos_test.go
@@ -1040,7 +1040,13 @@ func TestRepositoriesService_GetBranchProtection(t *testing.T) {
 		fmt.Fprintf(w, `{
 				"required_status_checks":{
 					"strict":true,
-					"contexts":["continuous-integration"]
+					"contexts":["continuous-integration"],
+					"checks": [
+						{
+							"context": "continuous-integration",
+							"app_id": null
+						}
+					]
 				},
 				"required_pull_request_reviews":{
 					"dismissal_restrictions":{
@@ -1081,6 +1087,11 @@ func TestRepositoriesService_GetBranchProtection(t *testing.T) {
 		RequiredStatusChecks: &RequiredStatusChecks{
 			Strict:   true,
 			Contexts: []string{"continuous-integration"},
+			Checks: []*RequiredStatusCheck{
+				{
+					Context: "continuous-integration",
+				},
+			},
 		},
 		RequiredPullRequestReviews: &PullRequestReviewsEnforcement{
 			DismissStaleReviews: true,
@@ -1141,7 +1152,13 @@ func TestRepositoriesService_GetBranchProtection_noDismissalRestrictions(t *test
 		fmt.Fprintf(w, `{
 				"required_status_checks":{
 					"strict":true,
-					"contexts":["continuous-integration"]
+					"contexts":["continuous-integration"],
+					"checks": [
+						{
+							"context": "continuous-integration",
+							"app_id": null
+						}
+					]
 				},
 				"required_pull_request_reviews":{
 					"dismiss_stale_reviews":true,
@@ -1169,6 +1186,11 @@ func TestRepositoriesService_GetBranchProtection_noDismissalRestrictions(t *test
 		RequiredStatusChecks: &RequiredStatusChecks{
 			Strict:   true,
 			Contexts: []string{"continuous-integration"},
+			Checks: []*RequiredStatusCheck{
+				{
+					Context: "continuous-integration",
+				},
+			},
 		},
 		RequiredPullRequestReviews: &PullRequestReviewsEnforcement{
 			DismissStaleReviews:          true,
@@ -1220,7 +1242,7 @@ func TestRepositoriesService_GetBranchProtection_branchNotProtected(t *testing.T
 	}
 }
 
-func TestRepositoriesService_UpdateBranchProtection(t *testing.T) {
+func TestRepositoriesService_UpdateBranchProtection_Contexts(t *testing.T) {
 	client, mux, _, teardown := setup()
 	defer teardown()
 
@@ -1257,7 +1279,13 @@ func TestRepositoriesService_UpdateBranchProtection(t *testing.T) {
 		fmt.Fprintf(w, `{
 			"required_status_checks":{
 				"strict":true,
-				"contexts":["continuous-integration"]
+				"contexts":["continuous-integration"],
+				"checks": [
+					{
+						"context": "continuous-integration",
+						"app_id": null
+					}
+				]
 			},
 			"required_pull_request_reviews":{
 				"dismissal_restrictions":{
@@ -1291,6 +1319,11 @@ func TestRepositoriesService_UpdateBranchProtection(t *testing.T) {
 		RequiredStatusChecks: &RequiredStatusChecks{
 			Strict:   true,
 			Contexts: []string{"continuous-integration"},
+			Checks: []*RequiredStatusCheck{
+				{
+					Context: "continuous-integration",
+				},
+			},
 		},
 		RequiredPullRequestReviews: &PullRequestReviewsEnforcement{
 			DismissStaleReviews: true,
@@ -1335,6 +1368,122 @@ func TestRepositoriesService_UpdateBranchProtection(t *testing.T) {
 	})
 }
 
+func TestRepositoriesService_UpdateBranchProtection_Checks(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	input := &ProtectionRequest{
+		RequiredStatusChecks: &RequiredStatusChecks{
+			Strict: true,
+			Checks: []*RequiredStatusCheck{
+				{
+					Context: "continuous-integration",
+				},
+			},
+		},
+		RequiredPullRequestReviews: &PullRequestReviewsEnforcementRequest{
+			DismissStaleReviews: true,
+			DismissalRestrictionsRequest: &DismissalRestrictionsRequest{
+				Users: &[]string{"uu"},
+				Teams: &[]string{"tt"},
+			},
+		},
+		Restrictions: &BranchRestrictionsRequest{
+			Users: []string{"u"},
+			Teams: []string{"t"},
+			Apps:  []string{"a"},
+		},
+	}
+
+	mux.HandleFunc("/repos/o/r/branches/b/protection", func(w http.ResponseWriter, r *http.Request) {
+		v := new(ProtectionRequest)
+		json.NewDecoder(r.Body).Decode(v)
+
+		testMethod(t, r, "PUT")
+		if !cmp.Equal(v, input) {
+			t.Errorf("Request body = %+v, want %+v", v, input)
+		}
+
+		// TODO: remove custom Accept header when this API fully launches
+		testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
+		fmt.Fprintf(w, `{
+			"required_status_checks":{
+				"strict":true,
+				"contexts":["continuous-integration"],
+				"checks": [
+					{
+						"context": "continuous-integration",
+						"app_id": null
+					}
+				]
+			},
+			"required_pull_request_reviews":{
+				"dismissal_restrictions":{
+					"users":[{
+						"id":3,
+						"login":"uu"
+					}],
+					"teams":[{
+						"id":4,
+						"slug":"tt"
+					}]
+				},
+				"dismiss_stale_reviews":true,
+				"require_code_owner_reviews":true
+			},
+			"restrictions":{
+				"users":[{"id":1,"login":"u"}],
+				"teams":[{"id":2,"slug":"t"}],
+				"apps":[{"id":3,"slug":"a"}]
+			}
+		}`)
+	})
+
+	ctx := context.Background()
+	protection, _, err := client.Repositories.UpdateBranchProtection(ctx, "o", "r", "b", input)
+	if err != nil {
+		t.Errorf("Repositories.UpdateBranchProtection returned error: %v", err)
+	}
+
+	want := &Protection{
+		RequiredStatusChecks: &RequiredStatusChecks{
+			Strict:   true,
+			Contexts: []string{"continuous-integration"},
+			Checks: []*RequiredStatusCheck{
+				{
+					Context: "continuous-integration",
+				},
+			},
+		},
+		RequiredPullRequestReviews: &PullRequestReviewsEnforcement{
+			DismissStaleReviews: true,
+			DismissalRestrictions: &DismissalRestrictions{
+				Users: []*User{
+					{Login: String("uu"), ID: Int64(3)},
+				},
+				Teams: []*Team{
+					{Slug: String("tt"), ID: Int64(4)},
+				},
+			},
+			RequireCodeOwnerReviews: true,
+		},
+		Restrictions: &BranchRestrictions{
+			Users: []*User{
+				{Login: String("u"), ID: Int64(1)},
+			},
+			Teams: []*Team{
+				{Slug: String("t"), ID: Int64(2)},
+			},
+			Apps: []*App{
+				{Slug: String("a"), ID: Int64(3)},
+			},
+		},
+	}
+	if !cmp.Equal(protection, want) {
+		t.Errorf("Repositories.UpdateBranchProtection returned %+v, want %+v", protection, want)
+	}
+}
+
 func TestRepositoriesService_RemoveBranchProtection(t *testing.T) {
 	client, mux, _, teardown := setup()
 	defer teardown()
@@ -1425,7 +1574,24 @@ func TestRepositoriesService_GetRequiredStatusChecks(t *testing.T) {
 		json.NewDecoder(r.Body).Decode(v)
 
 		testMethod(t, r, "GET")
-		fmt.Fprint(w, `{"strict": true,"contexts": ["x","y","z"]}`)
+		fmt.Fprint(w, `{
+			"strict": true,
+			"contexts": ["x","y","z"],
+			"checks": [
+				{
+					"context": "x",
+					"app_id": null
+				},
+				{
+					"context": "y",
+					"app_id": null
+				},
+				{
+					"context": "z",
+					"app_id": null
+				}
+			]
+		}`)
 	})
 
 	ctx := context.Background()
@@ -1437,6 +1603,17 @@ func TestRepositoriesService_GetRequiredStatusChecks(t *testing.T) {
 	want := &RequiredStatusChecks{
 		Strict:   true,
 		Contexts: []string{"x", "y", "z"},
+		Checks: []*RequiredStatusCheck{
+			{
+				Context: "x",
+			},
+			{
+				Context: "y",
+			},
+			{
+				Context: "z",
+			},
+		},
 	}
 	if !cmp.Equal(checks, want) {
 		t.Errorf("Repositories.GetRequiredStatusChecks returned %+v, want %+v", checks, want)
@@ -1483,7 +1660,7 @@ func TestRepositoriesService_GetRequiredStatusChecks_branchNotProtected(t *testi
 	}
 }
 
-func TestRepositoriesService_UpdateRequiredStatusChecks(t *testing.T) {
+func TestRepositoriesService_UpdateRequiredStatusChecks_Contexts(t *testing.T) {
 	client, mux, _, teardown := setup()
 	defer teardown()
 
@@ -1501,7 +1678,16 @@ func TestRepositoriesService_UpdateRequiredStatusChecks(t *testing.T) {
 			t.Errorf("Request body = %+v, want %+v", v, input)
 		}
 		testHeader(t, r, "Accept", mediaTypeV3)
-		fmt.Fprintf(w, `{"strict":true,"contexts":["continuous-integration"]}`)
+		fmt.Fprintf(w, `{
+			"strict":true,
+			"contexts":["continuous-integration"],
+			"checks": [
+				{
+					"context": "continuous-integration",
+					"app_id": null
+				}
+			]
+		}`)
 	})
 
 	ctx := context.Background()
@@ -1513,6 +1699,11 @@ func TestRepositoriesService_UpdateRequiredStatusChecks(t *testing.T) {
 	want := &RequiredStatusChecks{
 		Strict:   true,
 		Contexts: []string{"continuous-integration"},
+		Checks: []*RequiredStatusCheck{
+			{
+				Context: "continuous-integration",
+			},
+		},
 	}
 	if !cmp.Equal(statusChecks, want) {
 		t.Errorf("Repositories.UpdateRequiredStatusChecks returned %+v, want %+v", statusChecks, want)
@@ -1533,6 +1724,85 @@ func TestRepositoriesService_UpdateRequiredStatusChecks(t *testing.T) {
 	})
 }
 
+func TestRepositoriesService_UpdateRequiredStatusChecks_Checks(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	appID := int64(123)
+	noAppID := int64(-1)
+	input := &RequiredStatusChecksRequest{
+		Strict: Bool(true),
+		Checks: []*RequiredStatusCheck{
+			{
+				Context: "continuous-integration",
+			},
+			{
+				Context: "continuous-integration2",
+				AppID:   &appID,
+			},
+			{
+				Context: "continuous-integration3",
+				AppID:   &noAppID,
+			},
+		},
+	}
+
+	mux.HandleFunc("/repos/o/r/branches/b/protection/required_status_checks", func(w http.ResponseWriter, r *http.Request) {
+		v := new(RequiredStatusChecksRequest)
+		json.NewDecoder(r.Body).Decode(v)
+
+		testMethod(t, r, "PATCH")
+		if !cmp.Equal(v, input) {
+			t.Errorf("Request body = %+v, want %+v", v, input)
+		}
+		testHeader(t, r, "Accept", mediaTypeV3)
+		fmt.Fprintf(w, `{
+			"strict":true,
+			"contexts":["continuous-integration"],
+			"checks": [
+				{
+					"context": "continuous-integration",
+					"app_id": null
+				},
+				{
+					"context": "continuous-integration2",
+					"app_id": 123
+				},
+				{
+					"context": "continuous-integration3",
+					"app_id": null
+				}
+			]
+		}`)
+	})
+
+	ctx := context.Background()
+	statusChecks, _, err := client.Repositories.UpdateRequiredStatusChecks(ctx, "o", "r", "b", input)
+	if err != nil {
+		t.Errorf("Repositories.UpdateRequiredStatusChecks returned error: %v", err)
+	}
+
+	want := &RequiredStatusChecks{
+		Strict:   true,
+		Contexts: []string{"continuous-integration"},
+		Checks: []*RequiredStatusCheck{
+			{
+				Context: "continuous-integration",
+			},
+			{
+				Context: "continuous-integration2",
+				AppID:   &appID,
+			},
+			{
+				Context: "continuous-integration3",
+			},
+		},
+	}
+	if !cmp.Equal(statusChecks, want) {
+		t.Errorf("Repositories.UpdateRequiredStatusChecks returned %+v, want %+v", statusChecks, want)
+	}
+}
+
 func TestRepositoriesService_RemoveRequiredStatusChecks(t *testing.T) {
 	client, mux, _, teardown := setup()
 	defer teardown()