Repository: google/go-github
Pull request #2096 (2021-09-15 09:02:08)

Add support for apps webhook config endpoints
This adds support for two Apps API endpoints (see #2095)
- [Get a webhook configuration for an app](https://docs.github.com/en/rest/reference/apps#get-a-webhook-configuration-for-an-app)
- [Update a webhook configuration for an app](https://docs.github.com/en/rest/reference/apps#update-a-webhook-configuration-for-an-app)

Both endpoints require authentication as an app (with a JWT), which can be dealt with by the underlying transport.

A few notes:
- I reused / extended the `HookConfig` struct which was defined in `orgs_audit_logs.go`, since it represents the same object.

- The `InsecureSSL` field of the struct is a `*string`. However, GitHub only returns `"0"` or `"1"` (insecure SSL disabled / enabled), so I think it'd be more user-friendly to use a `*bool`, and write some logic so that boolean values are correctly (un)marshaled from `"0"`/`"1"`. I'd be happy to write the code to deal with this, but that would be a breaking change so I wanted to check with you first.

- This is probably out of scope of this PR, but the [`Hook` struct](https://github.com/google/go-github/blob/master/github/repos_hooks.go#L87) used for repository / organization webhooks endpoints is using a `map[string]interface{}` for the `Config` field, but I think it could be using the `HookConfig` struct as well since it represents the same object. Happy to make that change in a separate PR, but this would be a breaking change as well.

codecov[bot]: # [Codecov](https://codecov.io/gh/google/go-github/pull/2096?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google) Report
> Merging [#2096](https://codecov.io/gh/google/go-github/pull/2096?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google) (7f30b05) into [master](https://codecov.io/gh/google/go-github/commit/33ae6f3d80a32cc768320aad783f70c58a38b45a?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google) (33ae6f3) will **increase** coverage by `0.00%`.
> The diff coverage is `100.00%`.

[![Impacted file tree graph](https://codecov.io/gh/google/go-github/pull/2096/graphs/tree.svg?width=650&height=150&src=pr&token=EgYjGjZlI0&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google)](https://codecov.io/gh/google/go-github/pull/2096?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google)

```diff
@@           Coverage Diff           @@
##           master    #2096   +/-   ##
=======================================
  Coverage   97.77%   97.78%           
=======================================
  Files         109      110    +1     
  Lines        9724     9746   +22     
=======================================
+ Hits         9508     9530   +22     
  Misses        150      150           
  Partials       66       66           
```


| [Impacted Files](https://codecov.io/gh/google/go-github/pull/2096?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google) | Coverage Δ | |
|---|---|---|
| [github/orgs\_audit\_log.go](https://codecov.io/gh/google/go-github/pull/2096/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google#diff-Z2l0aHViL29yZ3NfYXVkaXRfbG9nLmdv) | `100.00% <ø> (ø)` | |
| [github/apps\_hooks.go](https://codecov.io/gh/google/go-github/pull/2096/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google#diff-Z2l0aHViL2FwcHNfaG9va3MuZ28=) | `100.00% <100.00%> (ø)` | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/google/go-github/pull/2096?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/google/go-github/pull/2096?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google). Last update [33ae6f3...7f30b05](https://codecov.io/gh/google/go-github/pull/2096?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google).


Patch:
diff --git a/.golangci.yml b/.golangci.yml
index afd9675f..db9a4d71 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -11,10 +11,10 @@ linters:
   # - gosec
     - misspell
     - nakedret
-  # - stylecheck
+    - stylecheck
   # - unconvert
   # - unparam
-  # - whitespace
+    - whitespace
   disable:
     - errcheck
     - gosimple
diff --git a/AUTHORS b/AUTHORS
index 2ae016f6..80bd26dd 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -155,6 +155,7 @@ ishan upadhyay <ishanupadhyay412@gmail.com>
 isqua <isqua@isqua.ru>
 Jacob Valdemar <jan@lunar.app>
 Jake Krammer <jake.krammer1@gmail.com>
+Jake White <jake@jwhite.network>
 Jameel Haffejee <RC1140@republiccommandos.co.za>
 James Cockbain <james.cockbain@ibm.com>
 James Loh <github@jloh.co>
@@ -353,4 +354,4 @@ Yosuke Akatsuka <yosuke.akatsuka@access-company.com>
 Yumikiyo Osanai <yumios.art@gmail.com>
 Yusuke Kuoka <ykuoka@gmail.com>
 Zach Latta <zach@zachlatta.com>
-zhouhaibing089 <zhouhaibing089@gmail.com>
+zhouhaibing089 <zhouhaibing089@gmail.com>
\ No newline at end of file
diff --git a/example/commitpr/main.go b/example/commitpr/main.go
index 61a39318..f437c84d 100644
--- a/example/commitpr/main.go
+++ b/example/commitpr/main.go
@@ -67,11 +67,11 @@ func getRef() (ref *github.Reference, err error) {
 	// We consider that an error means the branch has not been found and needs to
 	// be created.
 	if *commitBranch == *baseBranch {
-		return nil, errors.New("The commit branch does not exist but `-base-branch` is the same as `-commit-branch`")
+		return nil, errors.New("the commit branch does not exist but `-base-branch` is the same as `-commit-branch`")
 	}
 
 	if *baseBranch == "" {
-		return nil, errors.New("The `-base-branch` should not be set to an empty string when the branch specified by `-commit-branch` does not exists")
+		return nil, errors.New("the `-base-branch` should not be set to an empty string when the branch specified by `-commit-branch` does not exists")
 	}
 
 	var baseRef *github.Reference
diff --git a/github/actions_workflow_jobs.go b/github/actions_workflow_jobs.go
index 1102a756..86921bae 100644
--- a/github/actions_workflow_jobs.go
+++ b/github/actions_workflow_jobs.go
@@ -38,6 +38,8 @@ type WorkflowJob struct {
 	Name        *string     `json:"name,omitempty"`
 	Steps       []*TaskStep `json:"steps,omitempty"`
 	CheckRunURL *string     `json:"check_run_url,omitempty"`
+	// Labels represents runner labels from the `runs-on:` key from a GitHub Actions workflow.
+	Labels []string `json:"labels,omitempty"`
 }
 
 // Jobs represents a slice of repository action workflow job.
@@ -145,5 +147,4 @@ func (s *ActionsService) getWorkflowLogsFromURL(ctx context.Context, u string, f
 		resp, err = s.getWorkflowLogsFromURL(ctx, u, false)
 	}
 	return resp, err
-
 }
diff --git a/github/actions_workflow_runs.go b/github/actions_workflow_runs.go
index b2c40d47..3cd9df13 100644
--- a/github/actions_workflow_runs.go
+++ b/github/actions_workflow_runs.go
@@ -14,31 +14,33 @@ import (
 
 // WorkflowRun represents a repository action workflow run.
 type WorkflowRun struct {
-	ID             *int64         `json:"id,omitempty"`
-	Name           *string        `json:"name,omitempty"`
-	NodeID         *string        `json:"node_id,omitempty"`
-	HeadBranch     *string        `json:"head_branch,omitempty"`
-	HeadSHA        *string        `json:"head_sha,omitempty"`
-	RunNumber      *int           `json:"run_number,omitempty"`
-	Event          *string        `json:"event,omitempty"`
-	Status         *string        `json:"status,omitempty"`
-	Conclusion     *string        `json:"conclusion,omitempty"`
-	WorkflowID     *int64         `json:"workflow_id,omitempty"`
-	URL            *string        `json:"url,omitempty"`
-	HTMLURL        *string        `json:"html_url,omitempty"`
-	PullRequests   []*PullRequest `json:"pull_requests,omitempty"`
-	CreatedAt      *Timestamp     `json:"created_at,omitempty"`
-	UpdatedAt      *Timestamp     `json:"updated_at,omitempty"`
-	JobsURL        *string        `json:"jobs_url,omitempty"`
-	LogsURL        *string        `json:"logs_url,omitempty"`
-	CheckSuiteURL  *string        `json:"check_suite_url,omitempty"`
-	ArtifactsURL   *string        `json:"artifacts_url,omitempty"`
-	CancelURL      *string        `json:"cancel_url,omitempty"`
-	RerunURL       *string        `json:"rerun_url,omitempty"`
-	HeadCommit     *HeadCommit    `json:"head_commit,omitempty"`
-	WorkflowURL    *string        `json:"workflow_url,omitempty"`
-	Repository     *Repository    `json:"repository,omitempty"`
-	HeadRepository *Repository    `json:"head_repository,omitempty"`
+	ID               *int64         `json:"id,omitempty"`
+	Name             *string        `json:"name,omitempty"`
+	NodeID           *string        `json:"node_id,omitempty"`
+	HeadBranch       *string        `json:"head_branch,omitempty"`
+	HeadSHA          *string        `json:"head_sha,omitempty"`
+	RunNumber        *int           `json:"run_number,omitempty"`
+	Event            *string        `json:"event,omitempty"`
+	Status           *string        `json:"status,omitempty"`
+	Conclusion       *string        `json:"conclusion,omitempty"`
+	WorkflowID       *int64         `json:"workflow_id,omitempty"`
+	CheckSuiteID     *int64         `json:"check_suite_id,omitempty"`
+	CheckSuiteNodeID *string        `json:"check_suite_node_id,omitempty"`
+	URL              *string        `json:"url,omitempty"`
+	HTMLURL          *string        `json:"html_url,omitempty"`
+	PullRequests     []*PullRequest `json:"pull_requests,omitempty"`
+	CreatedAt        *Timestamp     `json:"created_at,omitempty"`
+	UpdatedAt        *Timestamp     `json:"updated_at,omitempty"`
+	JobsURL          *string        `json:"jobs_url,omitempty"`
+	LogsURL          *string        `json:"logs_url,omitempty"`
+	CheckSuiteURL    *string        `json:"check_suite_url,omitempty"`
+	ArtifactsURL     *string        `json:"artifacts_url,omitempty"`
+	CancelURL        *string        `json:"cancel_url,omitempty"`
+	RerunURL         *string        `json:"rerun_url,omitempty"`
+	HeadCommit       *HeadCommit    `json:"head_commit,omitempty"`
+	WorkflowURL      *string        `json:"workflow_url,omitempty"`
+	Repository       *Repository    `json:"repository,omitempty"`
+	HeadRepository   *Repository    `json:"head_repository,omitempty"`
 }
 
 // WorkflowRuns represents a slice of repository action workflow run.
diff --git a/github/apps_hooks.go b/github/apps_hooks.go
new file mode 100644
index 00000000..ed8396f4
--- /dev/null
+++ b/github/apps_hooks.go
@@ -0,0 +1,48 @@
+// Copyright 2021 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.
+
+package github
+
+import (
+	"context"
+)
+
+// GetHookConfig returns the webhook configuration for a GitHub App.
+// The underlying transport must be authenticated as an app.
+//
+// GitHub API docs: https://docs.github.com/en/free-pro-team@latest/rest/reference/apps#get-a-webhook-configuration-for-an-app
+func (s *AppsService) GetHookConfig(ctx context.Context) (*HookConfig, *Response, error) {
+	req, err := s.client.NewRequest("GET", "app/hook/config", nil)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	config := new(HookConfig)
+	resp, err := s.client.Do(ctx, req, &config)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return config, resp, nil
+}
+
+// UpdateHookConfig updates the webhook configuration for a GitHub App.
+// The underlying transport must be authenticated as an app.
+//
+// GitHub API docs: https://docs.github.com/en/free-pro-team@latest/rest/reference/apps#update-a-webhook-configuration-for-an-app
+func (s *AppsService) UpdateHookConfig(ctx context.Context, config *HookConfig) (*HookConfig, *Response, error) {
+	req, err := s.client.NewRequest("PATCH", "app/hook/config", config)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	c := new(HookConfig)
+	resp, err := s.client.Do(ctx, req, c)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return c, resp, nil
+}
diff --git a/github/code-scanning.go b/github/code-scanning.go
index dbaeb346..50264a0c 100644
--- a/github/code-scanning.go
+++ b/github/code-scanning.go
@@ -115,6 +115,8 @@ type AlertListOptions struct {
 
 	// Return code scanning alerts for a specific branch reference. The ref must be formatted as heads/<branch name>.
 	Ref string `url:"ref,omitempty"`
+
+	ListOptions
 }
 
 // ListAlertsForRepo lists code scanning alerts for a repository.
diff --git a/github/doc.go b/github/doc.go
index 44658741..87eda1de 100644
--- a/github/doc.go
+++ b/github/doc.go
@@ -73,6 +73,10 @@ BasicAuthTransport.
 
 GitHub Apps authentication can be provided by the
 https://github.com/bradleyfalzon/ghinstallation package.
+It supports both authentication as an installation, using an installation access token,
+and as an app, using a JWT.
+
+To authenticate as an installation:
 
 	import "github.com/bradleyfalzon/ghinstallation"
 
@@ -89,6 +93,23 @@ https://github.com/bradleyfalzon/ghinstallation package.
 		// Use client...
 	}
 
+To authenticate as an app, using a JWT:
+
+	import "github.com/bradleyfalzon/ghinstallation"
+
+	func main() {
+		// Wrap the shared transport for use with the application ID 1.
+		atr, err := ghinstallation.NewAppsTransportKeyFromFile(http.DefaultTransport, 1, "2016-10-19.private-key.pem")
+		if err != nil {
+			// Handle error.
+		}
+
+		// Use app transport with client
+		client := github.NewClient(&http.Client{Transport: atr})
+
+		// Use client...
+	}
+
 Rate Limiting
 
 GitHub imposes a rate limit on all API clients. Unauthenticated clients are
diff --git a/github/event.go b/github/event.go
index 8f1a0f2e..9241d028 100644
--- a/github/event.go
+++ b/github/event.go
@@ -30,6 +30,8 @@ func (e Event) String() string {
 // a value of the corresponding struct type will be returned.
 func (e *Event) ParsePayload() (payload interface{}, err error) {
 	switch *e.Type {
+	case "BranchProtectionRuleEvent":
+		payload = &BranchProtectionRuleEvent{}
 	case "CheckRunEvent":
 		payload = &CheckRunEvent{}
 	case "CheckSuiteEvent":
diff --git a/github/event_types.go b/github/event_types.go
index 384aa3a1..b60edb92 100644
--- a/github/event_types.go
+++ b/github/event_types.go
@@ -15,6 +15,19 @@ type RequestedAction struct {
 	Identifier string `json:"identifier"` // The integrator reference of the action requested by the user.
 }
 
+// BranchProtectionRuleEvent triggered when a check suite is "created", "edited", or "deleted".
+// The Webhook event name is "branch_protection_rule".
+//
+// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#branch_protection_rule
+type BranchProtectionRuleEvent struct {
+	Action  *string               `json:"action,omitempty"`
+	Rule    *BranchProtectionRule `json:"rule,omitempty"`
+	Changes *ProtectionChanges    `json:"changes,omitempty"`
+	Repo    *Repository           `json:"repository,omitempty"`
+	Org     *Organization         `json:"organization,omitempty"`
+	Sender  *User                 `json:"sender,omitempty"`
+}
+
 // CheckRunEvent is triggered when a check run is "created", "completed", or "rerequested".
 // The Webhook event name is "check_run".
 //
@@ -130,6 +143,9 @@ type DeployKeyEvent struct {
 
 	// The deploy key resource.
 	Key *Key `json:"key,omitempty"`
+
+	// The following fields are only populated by Webhook events.
+	Installation *Installation `json:"installation,omitempty"`
 }
 
 // DeploymentEvent represents a deployment.
@@ -186,7 +202,8 @@ type GitHubAppAuthorizationEvent struct {
 	Action *string `json:"action,omitempty"`
 
 	// The following fields are only populated by Webhook events.
-	Sender *User `json:"sender,omitempty"`
+	Sender       *User         `json:"sender,omitempty"`
+	Installation *Installation `json:"installation,omitempty"`
 }
 
 // Page represents a single Wiki page.
@@ -478,6 +495,9 @@ type MetaEvent struct {
 	// This will contain different keys based on the type of webhook it is: repository,
 	// organization, business, app, or GitHub Marketplace.
 	Hook *Hook `json:"hook,omitempty"`
+
+	// The following fields are only populated by Webhook events.
+	Installation *Installation `json:"installation,omitempty"`
 }
 
 // MilestoneEvent is triggered when a milestone is created, closed, opened, edited, or deleted.
@@ -551,6 +571,9 @@ type PackageEvent struct {
 	Repo    *Repository   `json:"repository,omitempty"`
 	Org     *Organization `json:"organization,omitempty"`
 	Sender  *User         `json:"sender,omitempty"`
+
+	// The following fields are only populated by Webhook events.
+	Installation *Installation `json:"installation,omitempty"`
 }
 
 // PageBuildEvent represents an attempted build of a GitHub Pages site, whether
@@ -939,6 +962,9 @@ type RepositoryVulnerabilityAlertEvent struct {
 
 	//The repository of the vulnerable dependency.
 	Repository *Repository `json:"repository,omitempty"`
+
+	// The following fields are only populated by Webhook events.
+	Installation *Installation `json:"installation,omitempty"`
 }
 
 // RepositoryVulnerabilityAlert represents a repository security alert.
@@ -969,9 +995,10 @@ type StarEvent struct {
 	StarredAt *Timestamp `json:"starred_at,omitempty"`
 
 	// The following fields are only populated by Webhook events.
-	Org    *Organization `json:"organization,omitempty"`
-	Repo   *Repository   `json:"repository,omitempty"`
-	Sender *User         `json:"sender,omitempty"`
+	Org          *Organization `json:"organization,omitempty"`
+	Repo         *Repository   `json:"repository,omitempty"`
+	Sender       *User         `json:"sender,omitempty"`
+	Installation *Installation `json:"installation,omitempty"`
 }
 
 // StatusEvent is triggered when the status of a Git commit changes.
@@ -1049,6 +1076,9 @@ type UserEvent struct {
 	Action     *string     `json:"action,omitempty"`
 	Enterprise *Enterprise `json:"enterprise,omitempty"`
 	Sender     *User       `json:"sender,omitempty"`
+
+	// The following fields are only populated by Webhook events.
+	Installation *Installation `json:"installation,omitempty"`
 }
 
 // WatchEvent is related to starring a repository, not watching. See this API
@@ -1078,23 +1108,28 @@ type WorkflowDispatchEvent struct {
 	Workflow *string         `json:"workflow,omitempty"`
 
 	// The following fields are only populated by Webhook events.
-	Repo   *Repository   `json:"repository,omitempty"`
-	Org    *Organization `json:"organization,omitempty"`
-	Sender *User         `json:"sender,omitempty"`
+	Repo         *Repository   `json:"repository,omitempty"`
+	Org          *Organization `json:"organization,omitempty"`
+	Sender       *User         `json:"sender,omitempty"`
+	Installation *Installation `json:"installation,omitempty"`
 }
 
 // WorkflowJobEvent is triggered when a job is queued, started or completed.
 //
-// GitHub API docs: pending
+// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#workflow_job
 type WorkflowJobEvent struct {
 	WorkflowJob *WorkflowJob `json:"workflow_job,omitempty"`
 
 	Action *string `json:"action,omitempty"`
 
 	// The following fields are only populated by Webhook events.
-	Org    *Organization `json:"organization,omitempty"`
-	Repo   *Repository   `json:"repository,omitempty"`
-	Sender *User         `json:"sender,omitempty"`
+
+	// Org is not nil when the webhook is configured for an organization or the event
+	// occurs from activity in a repository owned by an organization.
+	Org          *Organization `json:"organization,omitempty"`
+	Repo         *Repository   `json:"repository,omitempty"`
+	Sender       *User         `json:"sender,omitempty"`
+	Installation *Installation `json:"installation,omitempty"`
 }
 
 // WorkflowRunEvent is triggered when a GitHub Actions workflow run is requested or completed.
@@ -1106,7 +1141,8 @@ type WorkflowRunEvent struct {
 	WorkflowRun *WorkflowRun `json:"workflow_run,omitempty"`
 
 	// The following fields are only populated by Webhook events.
-	Org    *Organization `json:"organization,omitempty"`
-	Repo   *Repository   `json:"repository,omitempty"`
-	Sender *User         `json:"sender,omitempty"`
+	Org          *Organization `json:"organization,omitempty"`
+	Repo         *Repository   `json:"repository,omitempty"`
+	Sender       *User         `json:"sender,omitempty"`
+	Installation *Installation `json:"installation,omitempty"`
 }
diff --git a/github/github-accessors.go b/github/github-accessors.go
index 8422d6a7..4ca32031 100644
--- a/github/github-accessors.go
+++ b/github/github-accessors.go
@@ -1188,6 +1188,14 @@ func (a *AuthorizationUpdateRequest) GetNoteURL() string {
 	return *a.NoteURL
 }
 
+// GetFrom returns the From field if it's non-nil, zero value otherwise.
+func (a *AuthorizedActorsOnly) GetFrom() bool {
+	if a == nil || a.From == nil {
+		return false
+	}
+	return *a.From
+}
+
 // GetID returns the ID field if it's non-nil, zero value otherwise.
 func (a *Autolink) GetID() int64 {
 	if a == nil || a.ID == nil {
@@ -1364,6 +1372,230 @@ func (b *BranchPolicy) GetProtectedBranches() bool {
 	return *b.ProtectedBranches
 }
 
+// GetAdminEnforced returns the AdminEnforced field if it's non-nil, zero value otherwise.
+func (b *BranchProtectionRule) GetAdminEnforced() bool {
+	if b == nil || b.AdminEnforced == nil {
+		return false
+	}
+	return *b.AdminEnforced
+}
+
+// GetAllowDeletionsEnforcementLevel returns the AllowDeletionsEnforcementLevel field if it's non-nil, zero value otherwise.
+func (b *BranchProtectionRule) GetAllowDeletionsEnforcementLevel() string {
+	if b == nil || b.AllowDeletionsEnforcementLevel == nil {
+		return ""
+	}
+	return *b.AllowDeletionsEnforcementLevel
+}
+
+// GetAllowForcePushesEnforcementLevel returns the AllowForcePushesEnforcementLevel field if it's non-nil, zero value otherwise.
+func (b *BranchProtectionRule) GetAllowForcePushesEnforcementLevel() string {
+	if b == nil || b.AllowForcePushesEnforcementLevel == nil {
+		return ""
+	}
+	return *b.AllowForcePushesEnforcementLevel
+}
+
+// GetAuthorizedActorsOnly returns the AuthorizedActorsOnly field if it's non-nil, zero value otherwise.
+func (b *BranchProtectionRule) GetAuthorizedActorsOnly() bool {
+	if b == nil || b.AuthorizedActorsOnly == nil {
+		return false
+	}
+	return *b.AuthorizedActorsOnly
+}
+
+// GetAuthorizedDismissalActorsOnly returns the AuthorizedDismissalActorsOnly field if it's non-nil, zero value otherwise.
+func (b *BranchProtectionRule) GetAuthorizedDismissalActorsOnly() bool {
+	if b == nil || b.AuthorizedDismissalActorsOnly == nil {
+		return false
+	}
+	return *b.AuthorizedDismissalActorsOnly
+}
+
+// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise.
+func (b *BranchProtectionRule) GetCreatedAt() Timestamp {
+	if b == nil || b.CreatedAt == nil {
+		return Timestamp{}
+	}
+	return *b.CreatedAt
+}
+
+// GetDismissStaleReviewsOnPush returns the DismissStaleReviewsOnPush field if it's non-nil, zero value otherwise.
+func (b *BranchProtectionRule) GetDismissStaleReviewsOnPush() bool {
+	if b == nil || b.DismissStaleReviewsOnPush == nil {
+		return false
+	}
+	return *b.DismissStaleReviewsOnPush
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (b *BranchProtectionRule) GetID() int64 {
+	if b == nil || b.ID == nil {
+		return 0
+	}
+	return *b.ID
+}
+
+// GetIgnoreApprovalsFromContributors returns the IgnoreApprovalsFromContributors field if it's non-nil, zero value otherwise.
+func (b *BranchProtectionRule) GetIgnoreApprovalsFromContributors() bool {
+	if b == nil || b.IgnoreApprovalsFromContributors == nil {
+		return false
+	}
+	return *b.IgnoreApprovalsFromContributors
+}
+
+// GetLinearHistoryRequirementEnforcementLevel returns the LinearHistoryRequirementEnforcementLevel field if it's non-nil, zero value otherwise.
+func (b *BranchProtectionRule) GetLinearHistoryRequirementEnforcementLevel() string {
+	if b == nil || b.LinearHistoryRequirementEnforcementLevel == nil {
+		return ""
+	}
+	return *b.LinearHistoryRequirementEnforcementLevel
+}
+
+// GetMergeQueueEnforcementLevel returns the MergeQueueEnforcementLevel field if it's non-nil, zero value otherwise.
+func (b *BranchProtectionRule) GetMergeQueueEnforcementLevel() string {
+	if b == nil || b.MergeQueueEnforcementLevel == nil {
+		return ""
+	}
+	return *b.MergeQueueEnforcementLevel
+}
+
+// GetName returns the Name field if it's non-nil, zero value otherwise.
+func (b *BranchProtectionRule) GetName() string {
+	if b == nil || b.Name == nil {
+		return ""
+	}
+	return *b.Name
+}
+
+// GetPullRequestReviewsEnforcementLevel returns the PullRequestReviewsEnforcementLevel field if it's non-nil, zero value otherwise.
+func (b *BranchProtectionRule) GetPullRequestReviewsEnforcementLevel() string {
+	if b == nil || b.PullRequestReviewsEnforcementLevel == nil {
+		return ""
+	}
+	return *b.PullRequestReviewsEnforcementLevel
+}
+
+// GetRepositoryID returns the RepositoryID field if it's non-nil, zero value otherwise.
+func (b *BranchProtectionRule) GetRepositoryID() int64 {
+	if b == nil || b.RepositoryID == nil {
+		return 0
+	}
+	return *b.RepositoryID
+}
+
+// GetRequireCodeOwnerReview returns the RequireCodeOwnerReview field if it's non-nil, zero value otherwise.
+func (b *BranchProtectionRule) GetRequireCodeOwnerReview() bool {
+	if b == nil || b.RequireCodeOwnerReview == nil {
+		return false
+	}
+	return *b.RequireCodeOwnerReview
+}
+
+// GetRequiredApprovingReviewCount returns the RequiredApprovingReviewCount field if it's non-nil, zero value otherwise.
+func (b *BranchProtectionRule) GetRequiredApprovingReviewCount() int {
+	if b == nil || b.RequiredApprovingReviewCount == nil {
+		return 0
+	}
+	return *b.RequiredApprovingReviewCount
+}
+
+// GetRequiredConversationResolutionLevel returns the RequiredConversationResolutionLevel field if it's non-nil, zero value otherwise.
+func (b *BranchProtectionRule) GetRequiredConversationResolutionLevel() string {
+	if b == nil || b.RequiredConversationResolutionLevel == nil {
+		return ""
+	}
+	return *b.RequiredConversationResolutionLevel
+}
+
+// GetRequiredDeploymentsEnforcementLevel returns the RequiredDeploymentsEnforcementLevel field if it's non-nil, zero value otherwise.
+func (b *BranchProtectionRule) GetRequiredDeploymentsEnforcementLevel() string {
+	if b == nil || b.RequiredDeploymentsEnforcementLevel == nil {
+		return ""
+	}
+	return *b.RequiredDeploymentsEnforcementLevel
+}
+
+// GetRequiredStatusChecksEnforcementLevel returns the RequiredStatusChecksEnforcementLevel field if it's non-nil, zero value otherwise.
+func (b *BranchProtectionRule) GetRequiredStatusChecksEnforcementLevel() string {
+	if b == nil || b.RequiredStatusChecksEnforcementLevel == nil {
+		return ""
+	}
+	return *b.RequiredStatusChecksEnforcementLevel
+}
+
+// GetSignatureRequirementEnforcementLevel returns the SignatureRequirementEnforcementLevel field if it's non-nil, zero value otherwise.
+func (b *BranchProtectionRule) GetSignatureRequirementEnforcementLevel() string {
+	if b == nil || b.SignatureRequirementEnforcementLevel == nil {
+		return ""
+	}
+	return *b.SignatureRequirementEnforcementLevel
+}
+
+// GetStrictRequiredStatusChecksPolicy returns the StrictRequiredStatusChecksPolicy field if it's non-nil, zero value otherwise.
+func (b *BranchProtectionRule) GetStrictRequiredStatusChecksPolicy() bool {
+	if b == nil || b.StrictRequiredStatusChecksPolicy == nil {
+		return false
+	}
+	return *b.StrictRequiredStatusChecksPolicy
+}
+
+// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise.
+func (b *BranchProtectionRule) GetUpdatedAt() Timestamp {
+	if b == nil || b.UpdatedAt == nil {
+		return Timestamp{}
+	}
+	return *b.UpdatedAt
+}
+
+// GetAction returns the Action field if it's non-nil, zero value otherwise.
+func (b *BranchProtectionRuleEvent) GetAction() string {
+	if b == nil || b.Action == nil {
+		return ""
+	}
+	return *b.Action
+}
+
+// GetChanges returns the Changes field.
+func (b *BranchProtectionRuleEvent) GetChanges() *ProtectionChanges {
+	if b == nil {
+		return nil
+	}
+	return b.Changes
+}
+
+// GetOrg returns the Org field.
+func (b *BranchProtectionRuleEvent) GetOrg() *Organization {
+	if b == nil {
+		return nil
+	}
+	return b.Org
+}
+
+// GetRepo returns the Repo field.
+func (b *BranchProtectionRuleEvent) GetRepo() *Repository {
+	if b == nil {
+		return nil
+	}
+	return b.Repo
+}
+
+// GetRule returns the Rule field.
+func (b *BranchProtectionRuleEvent) GetRule() *BranchProtectionRule {
+	if b == nil {
+		return nil
+	}
+	return b.Rule
+}
+
+// GetSender returns the Sender field.
+func (b *BranchProtectionRuleEvent) GetSender() *User {
+	if b == nil {
+		return nil
+	}
+	return b.Sender
+}
+
 // GetApp returns the App field.
 func (c *CheckRun) GetApp() *App {
 	if c == nil {
@@ -3148,6 +3380,14 @@ func (d *DeployKeyEvent) GetAction() string {
 	return *d.Action
 }
 
+// GetInstallation returns the Installation field.
+func (d *DeployKeyEvent) GetInstallation() *Installation {
+	if d == nil {
+		return nil
+	}
+	return d.Installation
+}
+
 // GetKey returns the Key field.
 func (d *DeployKeyEvent) GetKey() *Key {
 	if d == nil {
@@ -4612,6 +4852,14 @@ func (g *GitHubAppAuthorizationEvent) GetAction() string {
 	return *g.Action
 }
 
+// GetInstallation returns the Installation field.
+func (g *GitHubAppAuthorizationEvent) GetInstallation() *Installation {
+	if g == nil {
+		return nil
+	}
+	return g.Installation
+}
+
 // GetSender returns the Sender field.
 func (g *GitHubAppAuthorizationEvent) GetSender() *User {
 	if g == nil {
@@ -4988,6 +5236,14 @@ func (h *HookConfig) GetInsecureSSL() string {
 	return *h.InsecureSSL
 }
 
+// GetSecret returns the Secret field if it's non-nil, zero value otherwise.
+func (h *HookConfig) GetSecret() string {
+	if h == nil || h.Secret == nil {
+		return ""
+	}
+	return *h.Secret
+}
+
 // GetURL returns the URL field if it's non-nil, zero value otherwise.
 func (h *HookConfig) GetURL() string {
 	if h == nil || h.URL == nil {
@@ -7796,6 +8052,14 @@ func (m *MetaEvent) GetHookID() int64 {
 	return *m.HookID
 }
 
+// GetInstallation returns the Installation field.
+func (m *MetaEvent) GetInstallation() *Installation {
+	if m == nil {
+		return nil
+	}
+	return m.Installation
+}
+
 // GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise.
 func (m *Metric) GetHTMLURL() string {
 	if m == nil || m.HTMLURL == nil {
@@ -8956,6 +9220,14 @@ func (p *Package) GetRegistry() *PackageRegistry {
 	return p.Registry
 }
 
+// GetRepository returns the Repository field.
+func (p *Package) GetRepository() *Repository {
+	if p == nil {
+		return nil
+	}
+	return p.Repository
+}
+
 // GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise.
 func (p *Package) GetUpdatedAt() Timestamp {
 	if p == nil || p.UpdatedAt == nil {
@@ -8964,6 +9236,30 @@ func (p *Package) GetUpdatedAt() Timestamp {
 	return *p.UpdatedAt
 }
 
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (p *Package) GetURL() string {
+	if p == nil || p.URL == nil {
+		return ""
+	}
+	return *p.URL
+}
+
+// GetVersionCount returns the VersionCount field if it's non-nil, zero value otherwise.
+func (p *Package) GetVersionCount() int64 {
+	if p == nil || p.VersionCount == nil {
+		return 0
+	}
+	return *p.VersionCount
+}
+
+// GetVisibility returns the Visibility field if it's non-nil, zero value otherwise.
+func (p *Package) GetVisibility() string {
+	if p == nil || p.Visibility == nil {
+		return ""
+	}
+	return *p.Visibility
+}
+
 // GetAction returns the Action field if it's non-nil, zero value otherwise.
 func (p *PackageEvent) GetAction() string {
 	if p == nil || p.Action == nil {
@@ -8972,6 +9268,14 @@ func (p *PackageEvent) GetAction() string {
 	return *p.Action
 }
 
+// GetInstallation returns the Installation field.
+func (p *PackageEvent) GetInstallation() *Installation {
+	if p == nil {
+		return nil
+	}
+	return p.Installation
+}
+
 // GetOrg returns the Org field.
 func (p *PackageEvent) GetOrg() *Organization {
 	if p == nil {
@@ -9100,6 +9404,46 @@ func (p *PackageFile) GetUpdatedAt() Timestamp {
 	return *p.UpdatedAt
 }
 
+// GetPackageType returns the PackageType field if it's non-nil, zero value otherwise.
+func (p *PackageListOptions) GetPackageType() string {
+	if p == nil || p.PackageType == nil {
+		return ""
+	}
+	return *p.PackageType
+}
+
+// GetState returns the State field if it's non-nil, zero value otherwise.
+func (p *PackageListOptions) GetState() string {
+	if p == nil || p.State == nil {
+		return ""
+	}
+	return *p.State
+}
+
+// GetVisibility returns the Visibility field if it's non-nil, zero value otherwise.
+func (p *PackageListOptions) GetVisibility() string {
+	if p == nil || p.Visibility == nil {
+		return ""
+	}
+	return *p.Visibility
+}
+
+// GetContainer returns the Container field.
+func (p *PackageMetadata) GetContainer() *PackageContainerMetadata {
+	if p == nil {
+		return nil
+	}
+	return p.Container
+}
+
+// GetPackageType returns the PackageType field if it's non-nil, zero value otherwise.
+func (p *PackageMetadata) GetPackageType() string {
+	if p == nil || p.PackageType == nil {
+		return ""
+	}
+	return *p.PackageType
+}
+
 // GetAboutURL returns the AboutURL field if it's non-nil, zero value otherwise.
 func (p *PackageRegistry) GetAboutURL() string {
 	if p == nil || p.AboutURL == nil {
@@ -9300,6 +9644,30 @@ func (p *PackageVersion) GetManifest() string {
 	return *p.Manifest
 }
 
+// GetMetadata returns the Metadata field.
+func (p *PackageVersion) GetMetadata() *PackageMetadata {
+	if p == nil {
+		return nil
+	}
+	return p.Metadata
+}
+
+// GetName returns the Name field if it's non-nil, zero value otherwise.
+func (p *PackageVersion) GetName() string {
+	if p == nil || p.Name == nil {
+		return ""
+	}
+	return *p.Name
+}
+
+// GetPackageHTMLURL returns the PackageHTMLURL field if it's non-nil, zero value otherwise.
+func (p *PackageVersion) GetPackageHTMLURL() string {
+	if p == nil || p.PackageHTMLURL == nil {
+		return ""
+	}
+	return *p.PackageHTMLURL
+}
+
 // GetPrerelease returns the Prerelease field if it's non-nil, zero value otherwise.
 func (p *PackageVersion) GetPrerelease() bool {
 	if p == nil || p.Prerelease == nil {
@@ -9356,6 +9724,14 @@ func (p *PackageVersion) GetUpdatedAt() Timestamp {
 	return *p.UpdatedAt
 }
 
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (p *PackageVersion) GetURL() string {
+	if p == nil || p.URL == nil {
+		return ""
+	}
+	return *p.URL
+}
+
 // GetVersion returns the Version field if it's non-nil, zero value otherwise.
 func (p *PackageVersion) GetVersion() string {
 	if p == nil || p.Version == nil {
@@ -10476,6 +10852,22 @@ func (p *Protection) GetRestrictions() *BranchRestrictions {
 	return p.Restrictions
 }
 
+// GetAuthorizedActorNames returns the AuthorizedActorNames field.
+func (p *ProtectionChanges) GetAuthorizedActorNames() *AuthorizedActorNames {
+	if p == nil {
+		return nil
+	}
+	return p.AuthorizedActorNames
+}
+
+// GetAuthorizedActorsOnly returns the AuthorizedActorsOnly field.
+func (p *ProtectionChanges) GetAuthorizedActorsOnly() *AuthorizedActorsOnly {
+	if p == nil {
+		return nil
+	}
+	return p.AuthorizedActorsOnly
+}
+
 // GetAllowDeletions returns the AllowDeletions field if it's non-nil, zero value otherwise.
 func (p *ProtectionRequest) GetAllowDeletions() bool {
 	if p == nil || p.AllowDeletions == nil {
@@ -14292,6 +14684,14 @@ func (r *RepositoryVulnerabilityAlertEvent) GetAlert() *RepositoryVulnerabilityA
 	return r.Alert
 }
 
+// GetInstallation returns the Installation field.
+func (r *RepositoryVulnerabilityAlertEvent) GetInstallation() *Installation {
+	if r == nil {
+		return nil
+	}
+	return r.Installation
+}
+
 // GetRepository returns the Repository field.
 func (r *RepositoryVulnerabilityAlertEvent) GetRepository() *Repository {
 	if r == nil {
@@ -14908,6 +15308,14 @@ func (s *StarEvent) GetAction() string {
 	return *s.Action
 }
 
+// GetInstallation returns the Installation field.
+func (s *StarEvent) GetInstallation() *Installation {
+	if s == nil {
+		return nil
+	}
+	return s.Installation
+}
+
 // GetOrg returns the Org field.
 func (s *StarEvent) GetOrg() *Organization {
 	if s == nil {
@@ -16852,6 +17260,14 @@ func (u *UserEvent) GetEnterprise() *Enterprise {
 	return u.Enterprise
 }
 
+// GetInstallation returns the Installation field.
+func (u *UserEvent) GetInstallation() *Installation {
+	if u == nil {
+		return nil
+	}
+	return u.Installation
+}
+
 // GetSender returns the Sender field.
 func (u *UserEvent) GetSender() *User {
 	if u == nil {
@@ -17468,6 +17884,14 @@ func (w *WorkflowBill) GetTotalMS() int64 {
 	return *w.TotalMS
 }
 
+// GetInstallation returns the Installation field.
+func (w *WorkflowDispatchEvent) GetInstallation() *Installation {
+	if w == nil {
+		return nil
+	}
+	return w.Installation
+}
+
 // GetOrg returns the Org field.
 func (w *WorkflowDispatchEvent) GetOrg() *Organization {
 	if w == nil {
@@ -17644,6 +18068,14 @@ func (w *WorkflowJobEvent) GetAction() string {
 	return *w.Action
 }
 
+// GetInstallation returns the Installation field.
+func (w *WorkflowJobEvent) GetInstallation() *Installation {
+	if w == nil {
+		return nil
+	}
+	return w.Installation
+}
+
 // GetOrg returns the Org field.
 func (w *WorkflowJobEvent) GetOrg() *Organization {
 	if w == nil {
@@ -17692,6 +18124,22 @@ func (w *WorkflowRun) GetCancelURL() string {
 	return *w.CancelURL
 }
 
+// GetCheckSuiteID returns the CheckSuiteID field if it's non-nil, zero value otherwise.
+func (w *WorkflowRun) GetCheckSuiteID() int64 {
+	if w == nil || w.CheckSuiteID == nil {
+		return 0
+	}
+	return *w.CheckSuiteID
+}
+
+// GetCheckSuiteNodeID returns the CheckSuiteNodeID field if it's non-nil, zero value otherwise.
+func (w *WorkflowRun) GetCheckSuiteNodeID() string {
+	if w == nil || w.CheckSuiteNodeID == nil {
+		return ""
+	}
+	return *w.CheckSuiteNodeID
+}
+
 // GetCheckSuiteURL returns the CheckSuiteURL field if it's non-nil, zero value otherwise.
 func (w *WorkflowRun) GetCheckSuiteURL() string {
 	if w == nil || w.CheckSuiteURL == nil {
@@ -17916,6 +18364,14 @@ func (w *WorkflowRunEvent) GetAction() string {
 	return *w.Action
 }
 
+// GetInstallation returns the Installation field.
+func (w *WorkflowRunEvent) GetInstallation() *Installation {
+	if w == nil {
+		return nil
+	}
+	return w.Installation
+}
+
 // GetOrg returns the Org field.
 func (w *WorkflowRunEvent) GetOrg() *Organization {
 	if w == nil {
diff --git a/github/github.go b/github/github.go
index a2727ccf..d4d7a54a 100644
--- a/github/github.go
+++ b/github/github.go
@@ -708,10 +708,10 @@ func (c *Client) checkRateLimitBeforeDo(req *http.Request, rateLimitCategory rat
 	return nil
 }
 
-// compareHttpResponse returns whether two http.Response objects are equal or not.
+// compareHTTPResponse returns whether two http.Response objects are equal or not.
 // Currently, only StatusCode is checked. This function is used when implementing the
 // Is(error) bool interface for the custom error types in this package.
-func compareHttpResponse(r1, r2 *http.Response) bool {
+func compareHTTPResponse(r1, r2 *http.Response) bool {
 	if r1 == nil && r2 == nil {
 		return true
 	}
@@ -761,7 +761,7 @@ func (r *ErrorResponse) Is(target error) bool {
 	}
 
 	if r.Message != v.Message || (r.DocumentationURL != v.DocumentationURL) ||
-		!compareHttpResponse(r.Response, v.Response) {
+		!compareHTTPResponse(r.Response, v.Response) {
 		return false
 	}
 
@@ -827,7 +827,7 @@ func (r *RateLimitError) Is(target error) bool {
 
 	return r.Rate == v.Rate &&
 		r.Message == v.Message &&
-		compareHttpResponse(r.Response, v.Response)
+		compareHTTPResponse(r.Response, v.Response)
 }
 
 // AcceptedError occurs when GitHub returns 202 Accepted response with an
@@ -881,7 +881,7 @@ func (r *AbuseRateLimitError) Is(target error) bool {
 
 	return r.Message == v.Message &&
 		r.RetryAfter == v.RetryAfter &&
-		compareHttpResponse(r.Response, v.Response)
+		compareHTTPResponse(r.Response, v.Response)
 }
 
 // sanitizeURL redacts the client_secret parameter from the URL which may be
diff --git a/github/messages.go b/github/messages.go
index e46435c9..4a03890c 100644
--- a/github/messages.go
+++ b/github/messages.go
@@ -45,6 +45,7 @@ const (
 var (
 	// eventTypeMapping maps webhooks types to their corresponding go-github struct types.
 	eventTypeMapping = map[string]string{
+		"branch_protection_rule":         "BranchProtectionRuleEvent",
 		"check_run":                      "CheckRunEvent",
 		"check_suite":                    "CheckSuiteEvent",
 		"commit_comment":                 "CommitCommentEvent",
@@ -191,7 +192,7 @@ func ValidatePayloadFromBody(contentType string, readable io.Reader, signature s
 		payload = []byte(form.Get(payloadFormParam))
 
 	default:
-		return nil, fmt.Errorf("Webhook request has unsupported Content-Type %q", contentType)
+		return nil, fmt.Errorf("webhook request has unsupported Content-Type %q", contentType)
 	}
 
 	// Only validate the signature if a secret token exists. This is intended for
diff --git a/github/orgs_audit_log.go b/github/orgs_audit_log.go
index 81f0edac..4b98ba69 100644
--- a/github/orgs_audit_log.go
+++ b/github/orgs_audit_log.go
@@ -24,6 +24,9 @@ type HookConfig struct {
 	ContentType *string `json:"content_type,omitempty"`
 	InsecureSSL *string `json:"insecure_ssl,omitempty"`
 	URL         *string `json:"url,omitempty"`
+
+	// Secret is returned obfuscated by GitHub, but it can be set for outgoing requests.
+	Secret *string `json:"secret,omitempty"`
 }
 
 // AuditEntry describes the fields that may be represented by various audit-log "action" entries.
diff --git a/github/orgs_packages.go b/github/orgs_packages.go
new file mode 100644
index 00000000..0c36f21c
--- /dev/null
+++ b/github/orgs_packages.go
@@ -0,0 +1,149 @@
+// Copyright 2021 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.
+
+package github
+
+import (
+	"context"
+	"fmt"
+)
+
+// List the packages for an organization.
+//
+// GitHub API docs: https://docs.github.com/en/rest/reference/packages#list-packages-for-an-organization
+func (s *OrganizationsService) ListPackages(ctx context.Context, org string, opts *PackageListOptions) ([]*Package, *Response, error) {
+	u := fmt.Sprintf("orgs/%v/packages", org)
+	u, err := addOptions(u, opts)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	req, err := s.client.NewRequest("GET", u, nil)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	var packages []*Package
+	resp, err := s.client.Do(ctx, req, &packages)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return packages, resp, nil
+}
+
+// Get a package by name from an organization.
+//
+// GitHub API docs: https://docs.github.com/en/rest/reference/packages#get-a-package-for-an-organization
+func (s *OrganizationsService) GetPackage(ctx context.Context, org, packageType, packageName string) (*Package, *Response, error) {
+	u := fmt.Sprintf("orgs/%v/packages/%v/%v", org, packageType, packageName)
+	req, err := s.client.NewRequest("GET", u, nil)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	var pack *Package
+	resp, err := s.client.Do(ctx, req, &pack)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return pack, resp, nil
+}
+
+// Delete a package from an organization.
+//
+// GitHub API docs: https://docs.github.com/en/rest/reference/packages#delete-a-package-for-an-organization
+func (s *OrganizationsService) DeletePackage(ctx context.Context, org, packageType, packageName string) (*Response, error) {
+	u := fmt.Sprintf("orgs/%v/packages/%v/%v", org, packageType, packageName)
+	req, err := s.client.NewRequest("DELETE", u, nil)
+	if err != nil {
+		return nil, err
+	}
+
+	return s.client.Do(ctx, req, nil)
+}
+
+// Restore a package to an organization.
+//
+// GitHub API docs: https://docs.github.com/en/rest/reference/packages#restore-a-package-for-an-organization
+func (s *OrganizationsService) RestorePackage(ctx context.Context, org, packageType, packageName string) (*Response, error) {
+	u := fmt.Sprintf("orgs/%v/packages/%v/%v/restore", org, packageType, packageName)
+	req, err := s.client.NewRequest("POST", u, nil)
+	if err != nil {
+		return nil, err
+	}
+
+	return s.client.Do(ctx, req, nil)
+}
+
+// Get all versions of a package in an organization.
+//
+// GitHub API docs: https://docs.github.com/en/rest/reference/packages#get-all-package-versions-for-a-package-owned-by-an-organization
+func (s *OrganizationsService) PackageGetAllVersions(ctx context.Context, org, packageType, packageName string, opts *PackageListOptions) ([]*PackageVersion, *Response, error) {
+	u := fmt.Sprintf("orgs/%v/packages/%v/%v/versions", org, packageType, packageName)
+	u, err := addOptions(u, opts)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	req, err := s.client.NewRequest("GET", u, nil)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	var versions []*PackageVersion
+	resp, err := s.client.Do(ctx, req, &versions)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return versions, resp, nil
+}
+
+// Get a specific version of a package in an organization.
+//
+// GitHub API docs: https://docs.github.com/en/rest/reference/packages#get-a-package-version-for-an-organization
+func (s *OrganizationsService) PackageGetVersion(ctx context.Context, org, packageType, packageName string, packageVersionID int64) (*PackageVersion, *Response, error) {
+	u := fmt.Sprintf("orgs/%v/packages/%v/%v/versions/%v", org, packageType, packageName, packageVersionID)
+	req, err := s.client.NewRequest("GET", u, nil)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	var version *PackageVersion
+	resp, err := s.client.Do(ctx, req, &version)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return version, resp, nil
+}
+
+// Delete a package version from an organization.
+//
+// GitHub API docs: https://docs.github.com/en/rest/reference/packages#delete-package-version-for-an-organization
+func (s *OrganizationsService) PackageDeleteVersion(ctx context.Context, org, packageType, packageName string, packageVersionID int64) (*Response, error) {
+	u := fmt.Sprintf("orgs/%v/packages/%v/%v/versions/%v", org, packageType, packageName, packageVersionID)
+	req, err := s.client.NewRequest("DELETE", u, nil)
+	if err != nil {
+		return nil, err
+	}
+
+	return s.client.Do(ctx, req, nil)
+}
+
+// Restore a package version to an organization.
+//
+// GitHub API docs: https://docs.github.com/en/rest/reference/packages#restore-package-version-for-an-organization
+func (s *OrganizationsService) PackageRestoreVersion(ctx context.Context, org, packageType, packageName string, packageVersionID int64) (*Response, error) {
+	u := fmt.Sprintf("orgs/%v/packages/%v/%v/versions/%v/restore", org, packageType, packageName, packageVersionID)
+	req, err := s.client.NewRequest("POST", u, nil)
+	if err != nil {
+		return nil, err
+	}
+
+	return s.client.Do(ctx, req, nil)
+}
diff --git a/github/packages.go b/github/packages.go
index 446e4faa..ef7df074 100644
--- a/github/packages.go
+++ b/github/packages.go
@@ -16,6 +16,10 @@ type Package struct {
 	Owner          *User            `json:"owner,omitempty"`
 	PackageVersion *PackageVersion  `json:"package_version,omitempty"`
 	Registry       *PackageRegistry `json:"registry,omitempty"`
+	URL            *string          `json:"url,omitempty"`
+	VersionCount   *int64           `json:"version_count,omitempty"`
+	Visibility     *string          `json:"visibility,omitempty"`
+	Repository     *Repository      `json:"repository,omitempty"`
 }
 
 func (p Package) String() string {
@@ -24,24 +28,28 @@ func (p Package) String() string {
 
 // PackageVersion represents a GitHub package version.
 type PackageVersion struct {
-	ID                  *int64          `json:"id,omitempty"`
-	Version             *string         `json:"version,omitempty"`
-	Summary             *string         `json:"summary,omitempty"`
-	Body                *string         `json:"body,omitempty"`
-	BodyHTML            *string         `json:"body_html,omitempty"`
-	Release             *PackageRelease `json:"release,omitempty"`
-	Manifest            *string         `json:"manifest,omitempty"`
-	HTMLURL             *string         `json:"html_url,omitempty"`
-	TagName             *string         `json:"tag_name,omitempty"`
-	TargetCommitish     *string         `json:"target_commitish,omitempty"`
-	TargetOID           *string         `json:"target_oid,omitempty"`
-	Draft               *bool           `json:"draft,omitempty"`
-	Prerelease          *bool           `json:"prerelease,omitempty"`
-	CreatedAt           *Timestamp      `json:"created_at,omitempty"`
-	UpdatedAt           *Timestamp      `json:"updated_at,omitempty"`
-	PackageFiles        []*PackageFile  `json:"package_files,omitempty"`
-	Author              *User           `json:"author,omitempty"`
-	InstallationCommand *string         `json:"installation_command,omitempty"`
+	ID                  *int64           `json:"id,omitempty"`
+	Version             *string          `json:"version,omitempty"`
+	Summary             *string          `json:"summary,omitempty"`
+	Body                *string          `json:"body,omitempty"`
+	BodyHTML            *string          `json:"body_html,omitempty"`
+	Release             *PackageRelease  `json:"release,omitempty"`
+	Manifest            *string          `json:"manifest,omitempty"`
+	HTMLURL             *string          `json:"html_url,omitempty"`
+	TagName             *string          `json:"tag_name,omitempty"`
+	TargetCommitish     *string          `json:"target_commitish,omitempty"`
+	TargetOID           *string          `json:"target_oid,omitempty"`
+	Draft               *bool            `json:"draft,omitempty"`
+	Prerelease          *bool            `json:"prerelease,omitempty"`
+	CreatedAt           *Timestamp       `json:"created_at,omitempty"`
+	UpdatedAt           *Timestamp       `json:"updated_at,omitempty"`
+	PackageFiles        []*PackageFile   `json:"package_files,omitempty"`
+	Author              *User            `json:"author,omitempty"`
+	InstallationCommand *string          `json:"installation_command,omitempty"`
+	Metadata            *PackageMetadata `json:"metadata,omitempty"`
+	PackageHTMLURL      *string          `json:"package_html_url,omitempty"`
+	Name                *string          `json:"name,omitempty"`
+	URL                 *string          `json:"url,omitempty"`
 }
 
 func (pv PackageVersion) String() string {
@@ -99,3 +107,37 @@ type PackageRegistry struct {
 func (r PackageRegistry) String() string {
 	return Stringify(r)
 }
+
+// PackageListOptions represents the optional list options for a package.
+type PackageListOptions struct {
+	// Visibility of packages "public", "internal" or "private".
+	Visibility *string `url:"visibility,omitempty"`
+
+	// PackageType represents the type of package.
+	// It can be one of "npm", "maven", "rubygems", "nuget", "docker", or "container".
+	PackageType *string `url:"package_type,omitempty"`
+
+	// State of package either "active" or "deleted".
+	State *string `url:"state,omitempty"`
+
+	ListOptions
+}
+
+// PackageMetadata represents metadata from a package.
+type PackageMetadata struct {
+	PackageType *string                   `json:"package_type,omitempty"`
+	Container   *PackageContainerMetadata `json:"container,omitempty"`
+}
+
+func (r PackageMetadata) String() string {
+	return Stringify(r)
+}
+
+// PackageContainerMetadata represents container metadata for docker container packages.
+type PackageContainerMetadata struct {
+	Tags []string `json:"tags,omitempty"`
+}
+
+func (r PackageContainerMetadata) String() string {
+	return Stringify(r)
+}
diff --git a/github/repos.go b/github/repos.go
index aab18d4d..f6236b43 100644
--- a/github/repos.go
+++ b/github/repos.go
@@ -767,6 +767,50 @@ type Protection struct {
 	RequiredConversationResolution *RequiredConversationResolution `json:"required_conversation_resolution"`
 }
 
+// BranchProtectionRule represents the rule applied to a repositories branch.
+type BranchProtectionRule struct {
+	ID                                       *int64     `json:"id,omitempty"`
+	RepositoryID                             *int64     `json:"repository_id,omitempty"`
+	Name                                     *string    `json:"name,omitempty"`
+	CreatedAt                                *Timestamp `json:"created_at,omitempty"`
+	UpdatedAt                                *Timestamp `json:"updated_at,omitempty"`
+	PullRequestReviewsEnforcementLevel       *string    `json:"pull_request_reviews_enforcement_level,omitempty"`
+	RequiredApprovingReviewCount             *int       `json:"required_approving_review_count,omitempty"`
+	DismissStaleReviewsOnPush                *bool      `json:"dismiss_stale_reviews_on_push,omitempty"`
+	AuthorizedDismissalActorsOnly            *bool      `json:"authorized_dismissal_actors_only,omitempty"`
+	IgnoreApprovalsFromContributors          *bool      `json:"ignore_approvals_from_contributors,omitempty"`
+	RequireCodeOwnerReview                   *bool      `json:"require_code_owner_review,omitempty"`
+	RequiredStatusChecks                     []string   `json:"required_status_checks,omitempty"`
+	RequiredStatusChecksEnforcementLevel     *string    `json:"required_status_checks_enforcement_level,omitempty"`
+	StrictRequiredStatusChecksPolicy         *bool      `json:"strict_required_status_checks_policy,omitempty"`
+	SignatureRequirementEnforcementLevel     *string    `json:"signature_requirement_enforcement_level,omitempty"`
+	LinearHistoryRequirementEnforcementLevel *string    `json:"linear_history_requirement_enforcement_level,omitempty"`
+	AdminEnforced                            *bool      `json:"admin_enforced,omitempty"`
+	AllowForcePushesEnforcementLevel         *string    `json:"allow_force_pushes_enforcement_level,omitempty"`
+	AllowDeletionsEnforcementLevel           *string    `json:"allow_deletions_enforcement_level,omitempty"`
+	MergeQueueEnforcementLevel               *string    `json:"merge_queue_enforcement_level,omitempty"`
+	RequiredDeploymentsEnforcementLevel      *string    `json:"required_deployments_enforcement_level,omitempty"`
+	RequiredConversationResolutionLevel      *string    `json:"required_conversation_resolution_level,omitempty"`
+	AuthorizedActorsOnly                     *bool      `json:"authorized_actors_only,omitempty"`
+	AuthorizedActorNames                     []string   `json:"authorized_actor_names,omitempty"`
+}
+
+// ProtectionChanges represents the changes to the rule if the BranchProtection was edited.
+type ProtectionChanges struct {
+	AuthorizedActorsOnly *AuthorizedActorsOnly `json:"authorized_actors_only,omitempty"`
+	AuthorizedActorNames *AuthorizedActorNames `json:"authorized_actor_names,omitempty"`
+}
+
+// AuthorizedActorNames represents who are authorized to edit the branch protection rules.
+type AuthorizedActorNames struct {
+	From []string `json:"from,omitempty"`
+}
+
+// AuthorizedActorsOnly represents if the branche rule can be edited by authorized actors only.
+type AuthorizedActorsOnly struct {
+	From *bool `json:"from,omitempty"`
+}
+
 // ProtectionRequest represents a request to create/edit a branch's protection.
 type ProtectionRequest struct {
 	RequiredStatusChecks       *RequiredStatusChecks                 `json:"required_status_checks"`
diff --git a/github/repos_contents.go b/github/repos_contents.go
index d88ae74b..86e11c0a 100644
--- a/github/repos_contents.go
+++ b/github/repos_contents.go
@@ -132,7 +132,7 @@ func (s *RepositoriesService) DownloadContents(ctx context.Context, owner, repo,
 	for _, contents := range dirContents {
 		if *contents.Name == filename {
 			if contents.DownloadURL == nil || *contents.DownloadURL == "" {
-				return nil, resp, fmt.Errorf("No download link found for %s", filepath)
+				return nil, resp, fmt.Errorf("no download link found for %s", filepath)
 			}
 			dlResp, err := s.client.client.Get(*contents.DownloadURL)
 			if err != nil {
@@ -141,7 +141,7 @@ func (s *RepositoriesService) DownloadContents(ctx context.Context, owner, repo,
 			return dlResp.Body, &Response{Response: dlResp}, nil
 		}
 	}
-	return nil, resp, fmt.Errorf("No file named %s found in %s", filename, dir)
+	return nil, resp, fmt.Errorf("no file named %s found in %s", filename, dir)
 }
 
 // DownloadContentsWithMeta is identical to DownloadContents but additionally
@@ -162,7 +162,7 @@ func (s *RepositoriesService) DownloadContentsWithMeta(ctx context.Context, owne
 	for _, contents := range dirContents {
 		if *contents.Name == filename {
 			if contents.DownloadURL == nil || *contents.DownloadURL == "" {
-				return nil, contents, resp, fmt.Errorf("No download link found for %s", filepath)
+				return nil, contents, resp, fmt.Errorf("no download link found for %s", filepath)
 			}
 			dlResp, err := s.client.client.Get(*contents.DownloadURL)
 			if err != nil {
@@ -171,7 +171,7 @@ func (s *RepositoriesService) DownloadContentsWithMeta(ctx context.Context, owne
 			return dlResp.Body, contents, &Response{Response: dlResp}, nil
 		}
 	}
-	return nil, nil, resp, fmt.Errorf("No file named %s found in %s", filename, dir)
+	return nil, nil, resp, fmt.Errorf("no file named %s found in %s", filename, dir)
 }
 
 // GetContents can return either the metadata and content of a single file
diff --git a/github/users_packages.go b/github/users_packages.go
new file mode 100644
index 00000000..d0684406
--- /dev/null
+++ b/github/users_packages.go
@@ -0,0 +1,207 @@
+// Copyright 2021 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.
+
+package github
+
+import (
+	"context"
+	"fmt"
+)
+
+// List the packages for a user. Passing the empty string for "user" will
+// list packages for the authenticated user.
+//
+// GitHub API docs: https://docs.github.com/en/rest/reference/packages#list-packages-for-the-authenticated-users-namespace
+// GitHub API docs: https://docs.github.com/en/rest/reference/packages#list-packages-for-a-user
+func (s *UsersService) ListPackages(ctx context.Context, user string, opts *PackageListOptions) ([]*Package, *Response, error) {
+	var u string
+	if user != "" {
+		u = fmt.Sprintf("user/%v/packages", user)
+	} else {
+		u = "user/packages"
+	}
+	u, err := addOptions(u, opts)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	req, err := s.client.NewRequest("GET", u, nil)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	var packages []*Package
+	resp, err := s.client.Do(ctx, req, &packages)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return packages, resp, nil
+}
+
+// Get a package by name for a user. Passing the empty string for "user" will
+// get the package for the authenticated user.
+//
+// GitHub API docs: https://docs.github.com/en/rest/reference/packages#get-a-package-for-the-authenticated-user
+// GitHub API docs: https://docs.github.com/en/rest/reference/packages#get-a-package-for-a-user
+func (s *UsersService) GetPackage(ctx context.Context, user, packageType, packageName string) (*Package, *Response, error) {
+	var u string
+	if user != "" {
+		u = fmt.Sprintf("users/%v/packages/%v/%v", user, packageType, packageName)
+	} else {
+		u = fmt.Sprintf("user/packages/%v/%v", packageType, packageName)
+	}
+
+	req, err := s.client.NewRequest("GET", u, nil)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	var pack *Package
+	resp, err := s.client.Do(ctx, req, &pack)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return pack, resp, nil
+}
+
+// Delete a package from a user. Passing the empty string for "user" will
+// delete the package for the authenticated user.
+//
+// GitHub API docs: https://docs.github.com/en/rest/reference/packages#delete-a-package-for-the-authenticated-user
+// GitHub API docs: https://docs.github.com/en/rest/reference/packages#delete-a-package-for-a-user
+func (s *UsersService) DeletePackage(ctx context.Context, user, packageType, packageName string) (*Response, error) {
+	var u string
+	if user != "" {
+		u = fmt.Sprintf("users/%v/packages/%v/%v", user, packageType, packageName)
+	} else {
+		u = fmt.Sprintf("user/packages/%v/%v", packageType, packageName)
+	}
+
+	req, err := s.client.NewRequest("DELETE", u, nil)
+	if err != nil {
+		return nil, err
+	}
+
+	return s.client.Do(ctx, req, nil)
+}
+
+// Restore a package to a user. Passing the empty string for "user" will
+// restore the package for the authenticated user.
+//
+// GitHub API docs: https://docs.github.com/en/rest/reference/packages#restore-a-package-for-the-authenticated-user
+// GitHub API docs: https://docs.github.com/en/rest/reference/packages#restore-a-package-for-a-user
+func (s *UsersService) RestorePackage(ctx context.Context, user, packageType, packageName string) (*Response, error) {
+	var u string
+	if user != "" {
+		u = fmt.Sprintf("users/%v/packages/%v/%v/restore", user, packageType, packageName)
+	} else {
+		u = fmt.Sprintf("user/packages/%v/%v/restore", packageType, packageName)
+	}
+
+	req, err := s.client.NewRequest("POST", u, nil)
+	if err != nil {
+		return nil, err
+	}
+
+	return s.client.Do(ctx, req, nil)
+}
+
+// Get all versions of a package for a user. Passing the empty string for "user" will
+// get versions for the authenticated user.
+//
+// GitHub API docs: https://docs.github.com/en/rest/reference/packages#get-all-package-versions-for-a-package-owned-by-the-authenticated-user
+// GitHub API docs: https://docs.github.com/en/rest/reference/users#delete-an-email-address-for-the-authenticated-user
+func (s *UsersService) PackageGetAllVersions(ctx context.Context, user, packageType, packageName string) ([]*PackageVersion, *Response, error) {
+	var u string
+	if user != "" {
+		u = fmt.Sprintf("users/%v/packages/%v/%v/versions", user, packageType, packageName)
+	} else {
+		u = fmt.Sprintf("user/packages/%v/%v/versions", packageType, packageName)
+	}
+
+	req, err := s.client.NewRequest("GET", u, nil)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	var versions []*PackageVersion
+	resp, err := s.client.Do(ctx, req, &versions)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return versions, resp, nil
+}
+
+// Get a specific version of a package for a user. Passing the empty string for "user" will
+// get the version for the authenticated user.
+//
+// GitHub API docs: https://docs.github.com/en/rest/reference/packages#get-a-package-version-for-the-authenticated-user
+// GitHub API docs: https://docs.github.com/en/rest/reference/packages#get-a-package-version-for-a-user
+func (s *UsersService) PackageGetVersion(ctx context.Context, user, packageType, packageName string, packageVersionID int64) (*PackageVersion, *Response, error) {
+	var u string
+	if user != "" {
+		u = fmt.Sprintf("users/%v/packages/%v/%v/versions/%v", user, packageType, packageName, packageVersionID)
+	} else {
+		u = fmt.Sprintf("user/packages/%v/%v/versions/%v", packageType, packageName, packageVersionID)
+	}
+
+	req, err := s.client.NewRequest("GET", u, nil)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	var version *PackageVersion
+	resp, err := s.client.Do(ctx, req, &version)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return version, resp, nil
+}
+
+// Delete a package version for a user. Passing the empty string for "user" will
+// delete the version for the authenticated user.
+//
+// GitHub API docs: https://docs.github.com/en/rest/reference/packages#delete-a-package-version-for-the-authenticated-user
+// GitHub API docs: https://docs.github.com/en/rest/reference/packages#delete-package-version-for-a-user
+func (s *UsersService) PackageDeleteVersion(ctx context.Context, user, packageType, packageName string, packageVersionID int64) (*Response, error) {
+	var u string
+	if user != "" {
+		u = fmt.Sprintf("users/%v/packages/%v/%v/versions/%v", user, packageType, packageName, packageVersionID)
+	} else {
+		u = fmt.Sprintf("user/packages/%v/%v/versions/%v", packageType, packageName, packageVersionID)
+	}
+
+	req, err := s.client.NewRequest("DELETE", u, nil)
+	if err != nil {
+		return nil, err
+	}
+
+	return s.client.Do(ctx, req, nil)
+}
+
+// Restore a package version to a user. Passing the empty string for "user" will
+// restore the version for the authenticated user.
+//
+// GitHub API docs: https://docs.github.com/en/rest/reference/packages#restore-a-package-version-for-the-authenticated-user
+// GitHub API docs: https://docs.github.com/en/rest/reference/packages#restore-package-version-for-a-user
+func (s *UsersService) PackageRestoreVersion(ctx context.Context, user, packageType, packageName string, packageVersionID int64) (*Response, error) {
+	var u string
+	if user != "" {
+		u = fmt.Sprintf("users/%v/packages/%v/%v/versions/%v/restore", user, packageType, packageName, packageVersionID)
+	} else {
+		u = fmt.Sprintf("user/packages/%v/%v/versions/%v/restore", packageType, packageName, packageVersionID)
+	}
+
+	req, err := s.client.NewRequest("POST", u, nil)
+	if err != nil {
+		return nil, err
+	}
+
+	return s.client.Do(ctx, req, nil)
+}
diff --git a/update-urls/main.go b/update-urls/main.go
index 248c7104..0e3f1eb0 100644
--- a/update-urls/main.go
+++ b/update-urls/main.go
@@ -199,10 +199,10 @@ func validateRewriteURLs(usedHelpers usedHelpersMap, endpointsByFilename endpoin
 				path = strings.ReplaceAll(path, "%s", "%v")
 
 				// Check the overrides.
-				endpoint.checkHttpMethodOverride(path)
+				endpoint.checkHTTPMethodOverride(path)
 
 				methodAndPath := fmt.Sprintf("%v %v", endpoint.httpMethod, path)
-				url, ok := docCache.UrlByMethodAndPath(methodAndPath)
+				url, ok := docCache.URLByMethodAndPath(methodAndPath)
 				if !ok {
 					if i := len(endpoint.endpointComments); i > 0 {
 						pos := fileRewriter.Position(endpoint.endpointComments[i-1].Pos())
@@ -529,7 +529,7 @@ func resolveHelpersAndCacheDocs(endpoints endpointsMap, docCache documentCacheWr
 }
 
 type documentCacheReader interface {
-	UrlByMethodAndPath(string) (string, bool)
+	URLByMethodAndPath(string) (string, bool)
 }
 
 type documentCacheWriter interface {
@@ -542,7 +542,7 @@ type documentCache struct {
 	urlByMethodAndPath map[string]string
 }
 
-func (dc *documentCache) UrlByMethodAndPath(methodAndPath string) (string, bool) {
+func (dc *documentCache) URLByMethodAndPath(methodAndPath string) (string, bool) {
 	url, ok := dc.urlByMethodAndPath[methodAndPath]
 	return url, ok
 }
@@ -657,7 +657,7 @@ func (e *Endpoint) String() string {
 	return b.String()
 }
 
-func (e *Endpoint) checkHttpMethodOverride(path string) {
+func (e *Endpoint) checkHTTPMethodOverride(path string) {
 	lookupOverride := fmt.Sprintf("%v.%v: %v %v", e.serviceName, e.endpointName, e.httpMethod, path)
 	logf("Looking up override for %q", lookupOverride)
 	if v, ok := methodOverrides[lookupOverride]; ok {
@@ -747,7 +747,7 @@ func processAST(filename string, f *ast.File, services servicesMap, endpoints en
 				stdRefLines:        stdRefLines,
 				endpointComments:   endpointComments,
 			}
-			// ep.checkHttpMethodOverride("")
+			// ep.checkHTTPMethodOverride("")
 			endpoints[fullName] = ep
 			logf("endpoints[%q] = %#v", fullName, endpoints[fullName])
 			if ep.httpMethod == "" && (ep.helperMethod == "" || len(ep.urlFormats) == 0) {


Test patch:
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 17b14291..991c5cb3 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -14,7 +14,7 @@ jobs:
   test:
     strategy:
       matrix:
-        go-version: [1.x, 1.15.x]
+        go-version: [1.x, 1.16.x]
         platform: [ubuntu-latest]
         include:
           # include windows, but only with the latest Go version, since there
diff --git a/github/actions_workflow_runs_test.go b/github/actions_workflow_runs_test.go
index 14274d53..6803ace0 100644
--- a/github/actions_workflow_runs_test.go
+++ b/github/actions_workflow_runs_test.go
@@ -295,7 +295,6 @@ func TestActionService_ListRepositoryWorkflowRuns(t *testing.T) {
 		"workflow_runs":[
 			{"id":298499444,"run_number":301,"created_at":"2020-04-11T11:14:54Z","updated_at":"2020-04-11T11:14:54Z"},
 			{"id":298499445,"run_number":302,"created_at":"2020-04-11T11:14:54Z","updated_at":"2020-04-11T11:14:54Z"}]}`)
-
 	})
 
 	opts := &ListWorkflowRunsOptions{ListOptions: ListOptions{Page: 2, PerPage: 2}}
diff --git a/github/apps_hooks_test.go b/github/apps_hooks_test.go
new file mode 100644
index 00000000..b00a74b7
--- /dev/null
+++ b/github/apps_hooks_test.go
@@ -0,0 +1,103 @@
+// Copyright 2021 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.
+
+package github
+
+import (
+	"context"
+	"fmt"
+	"net/http"
+	"testing"
+
+	"github.com/google/go-cmp/cmp"
+)
+
+func TestAppsService_GetHookConfig(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/app/hook/config", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "GET")
+		fmt.Fprint(w, `{
+			"content_type": "json",
+			"insecure_ssl": "0",
+			"secret": "********",
+			"url": "https://example.com/webhook"
+		}`)
+	})
+
+	ctx := context.Background()
+	config, _, err := client.Apps.GetHookConfig(ctx)
+	if err != nil {
+		t.Errorf("Apps.GetHookConfig returned error: %v", err)
+	}
+
+	want := &HookConfig{
+		ContentType: String("json"),
+		InsecureSSL: String("0"),
+		Secret:      String("********"),
+		URL:         String("https://example.com/webhook"),
+	}
+	if !cmp.Equal(config, want) {
+		t.Errorf("Apps.GetHookConfig returned %+v, want %+v", config, want)
+	}
+
+	const methodName = "GetHookConfig"
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		got, resp, err := client.Apps.GetHookConfig(ctx)
+		if got != nil {
+			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+		}
+		return resp, err
+	})
+}
+
+func TestAppsService_UpdateHookConfig(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	input := &HookConfig{
+		ContentType: String("json"),
+		InsecureSSL: String("1"),
+		Secret:      String("s"),
+		URL:         String("u"),
+	}
+
+	mux.HandleFunc("/app/hook/config", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "PATCH")
+		testBody(t, r, `{"content_type":"json","insecure_ssl":"1","url":"u","secret":"s"}`+"\n")
+		fmt.Fprint(w, `{
+			"content_type": "json",
+			"insecure_ssl": "1",
+			"secret": "********",
+			"url": "u"
+		}`)
+	})
+
+	ctx := context.Background()
+	config, _, err := client.Apps.UpdateHookConfig(ctx, input)
+	if err != nil {
+		t.Errorf("Apps.UpdateHookConfig returned error: %v", err)
+	}
+
+	want := &HookConfig{
+		ContentType: String("json"),
+		InsecureSSL: String("1"),
+		Secret:      String("********"),
+		URL:         String("u"),
+	}
+	if !cmp.Equal(config, want) {
+		t.Errorf("Apps.UpdateHookConfig returned %+v, want %+v", config, want)
+	}
+
+	const methodName = "UpdateHookConfig"
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		got, resp, err := client.Apps.UpdateHookConfig(ctx, input)
+		if got != nil {
+			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+		}
+		return resp, err
+	})
+}
diff --git a/github/enterprise_audit_log_test.go b/github/enterprise_audit_log_test.go
index 9f6f4a85..2e91346e 100644
--- a/github/enterprise_audit_log_test.go
+++ b/github/enterprise_audit_log_test.go
@@ -96,5 +96,4 @@ func TestEnterpriseService_GetAuditLog(t *testing.T) {
 		}
 		return resp, err
 	})
-
 }
diff --git a/github/github-accessors_test.go b/github/github-accessors_test.go
index df604c44..eda6a36b 100644
--- a/github/github-accessors_test.go
+++ b/github/github-accessors_test.go
@@ -1417,6 +1417,16 @@ func TestAuthorizationUpdateRequest_GetNoteURL(tt *testing.T) {
 	a.GetNoteURL()
 }
 
+func TestAuthorizedActorsOnly_GetFrom(tt *testing.T) {
+	var zeroValue bool
+	a := &AuthorizedActorsOnly{From: &zeroValue}
+	a.GetFrom()
+	a = &AuthorizedActorsOnly{}
+	a.GetFrom()
+	a = nil
+	a.GetFrom()
+}
+
 func TestAutolink_GetID(tt *testing.T) {
 	var zeroValue int64
 	a := &Autolink{ID: &zeroValue}
@@ -1631,6 +1641,271 @@ func TestBranchPolicy_GetProtectedBranches(tt *testing.T) {
 	b.GetProtectedBranches()
 }
 
+func TestBranchProtectionRule_GetAdminEnforced(tt *testing.T) {
+	var zeroValue bool
+	b := &BranchProtectionRule{AdminEnforced: &zeroValue}
+	b.GetAdminEnforced()
+	b = &BranchProtectionRule{}
+	b.GetAdminEnforced()
+	b = nil
+	b.GetAdminEnforced()
+}
+
+func TestBranchProtectionRule_GetAllowDeletionsEnforcementLevel(tt *testing.T) {
+	var zeroValue string
+	b := &BranchProtectionRule{AllowDeletionsEnforcementLevel: &zeroValue}
+	b.GetAllowDeletionsEnforcementLevel()
+	b = &BranchProtectionRule{}
+	b.GetAllowDeletionsEnforcementLevel()
+	b = nil
+	b.GetAllowDeletionsEnforcementLevel()
+}
+
+func TestBranchProtectionRule_GetAllowForcePushesEnforcementLevel(tt *testing.T) {
+	var zeroValue string
+	b := &BranchProtectionRule{AllowForcePushesEnforcementLevel: &zeroValue}
+	b.GetAllowForcePushesEnforcementLevel()
+	b = &BranchProtectionRule{}
+	b.GetAllowForcePushesEnforcementLevel()
+	b = nil
+	b.GetAllowForcePushesEnforcementLevel()
+}
+
+func TestBranchProtectionRule_GetAuthorizedActorsOnly(tt *testing.T) {
+	var zeroValue bool
+	b := &BranchProtectionRule{AuthorizedActorsOnly: &zeroValue}
+	b.GetAuthorizedActorsOnly()
+	b = &BranchProtectionRule{}
+	b.GetAuthorizedActorsOnly()
+	b = nil
+	b.GetAuthorizedActorsOnly()
+}
+
+func TestBranchProtectionRule_GetAuthorizedDismissalActorsOnly(tt *testing.T) {
+	var zeroValue bool
+	b := &BranchProtectionRule{AuthorizedDismissalActorsOnly: &zeroValue}
+	b.GetAuthorizedDismissalActorsOnly()
+	b = &BranchProtectionRule{}
+	b.GetAuthorizedDismissalActorsOnly()
+	b = nil
+	b.GetAuthorizedDismissalActorsOnly()
+}
+
+func TestBranchProtectionRule_GetCreatedAt(tt *testing.T) {
+	var zeroValue Timestamp
+	b := &BranchProtectionRule{CreatedAt: &zeroValue}
+	b.GetCreatedAt()
+	b = &BranchProtectionRule{}
+	b.GetCreatedAt()
+	b = nil
+	b.GetCreatedAt()
+}
+
+func TestBranchProtectionRule_GetDismissStaleReviewsOnPush(tt *testing.T) {
+	var zeroValue bool
+	b := &BranchProtectionRule{DismissStaleReviewsOnPush: &zeroValue}
+	b.GetDismissStaleReviewsOnPush()
+	b = &BranchProtectionRule{}
+	b.GetDismissStaleReviewsOnPush()
+	b = nil
+	b.GetDismissStaleReviewsOnPush()
+}
+
+func TestBranchProtectionRule_GetID(tt *testing.T) {
+	var zeroValue int64
+	b := &BranchProtectionRule{ID: &zeroValue}
+	b.GetID()
+	b = &BranchProtectionRule{}
+	b.GetID()
+	b = nil
+	b.GetID()
+}
+
+func TestBranchProtectionRule_GetIgnoreApprovalsFromContributors(tt *testing.T) {
+	var zeroValue bool
+	b := &BranchProtectionRule{IgnoreApprovalsFromContributors: &zeroValue}
+	b.GetIgnoreApprovalsFromContributors()
+	b = &BranchProtectionRule{}
+	b.GetIgnoreApprovalsFromContributors()
+	b = nil
+	b.GetIgnoreApprovalsFromContributors()
+}
+
+func TestBranchProtectionRule_GetLinearHistoryRequirementEnforcementLevel(tt *testing.T) {
+	var zeroValue string
+	b := &BranchProtectionRule{LinearHistoryRequirementEnforcementLevel: &zeroValue}
+	b.GetLinearHistoryRequirementEnforcementLevel()
+	b = &BranchProtectionRule{}
+	b.GetLinearHistoryRequirementEnforcementLevel()
+	b = nil
+	b.GetLinearHistoryRequirementEnforcementLevel()
+}
+
+func TestBranchProtectionRule_GetMergeQueueEnforcementLevel(tt *testing.T) {
+	var zeroValue string
+	b := &BranchProtectionRule{MergeQueueEnforcementLevel: &zeroValue}
+	b.GetMergeQueueEnforcementLevel()
+	b = &BranchProtectionRule{}
+	b.GetMergeQueueEnforcementLevel()
+	b = nil
+	b.GetMergeQueueEnforcementLevel()
+}
+
+func TestBranchProtectionRule_GetName(tt *testing.T) {
+	var zeroValue string
+	b := &BranchProtectionRule{Name: &zeroValue}
+	b.GetName()
+	b = &BranchProtectionRule{}
+	b.GetName()
+	b = nil
+	b.GetName()
+}
+
+func TestBranchProtectionRule_GetPullRequestReviewsEnforcementLevel(tt *testing.T) {
+	var zeroValue string
+	b := &BranchProtectionRule{PullRequestReviewsEnforcementLevel: &zeroValue}
+	b.GetPullRequestReviewsEnforcementLevel()
+	b = &BranchProtectionRule{}
+	b.GetPullRequestReviewsEnforcementLevel()
+	b = nil
+	b.GetPullRequestReviewsEnforcementLevel()
+}
+
+func TestBranchProtectionRule_GetRepositoryID(tt *testing.T) {
+	var zeroValue int64
+	b := &BranchProtectionRule{RepositoryID: &zeroValue}
+	b.GetRepositoryID()
+	b = &BranchProtectionRule{}
+	b.GetRepositoryID()
+	b = nil
+	b.GetRepositoryID()
+}
+
+func TestBranchProtectionRule_GetRequireCodeOwnerReview(tt *testing.T) {
+	var zeroValue bool
+	b := &BranchProtectionRule{RequireCodeOwnerReview: &zeroValue}
+	b.GetRequireCodeOwnerReview()
+	b = &BranchProtectionRule{}
+	b.GetRequireCodeOwnerReview()
+	b = nil
+	b.GetRequireCodeOwnerReview()
+}
+
+func TestBranchProtectionRule_GetRequiredApprovingReviewCount(tt *testing.T) {
+	var zeroValue int
+	b := &BranchProtectionRule{RequiredApprovingReviewCount: &zeroValue}
+	b.GetRequiredApprovingReviewCount()
+	b = &BranchProtectionRule{}
+	b.GetRequiredApprovingReviewCount()
+	b = nil
+	b.GetRequiredApprovingReviewCount()
+}
+
+func TestBranchProtectionRule_GetRequiredConversationResolutionLevel(tt *testing.T) {
+	var zeroValue string
+	b := &BranchProtectionRule{RequiredConversationResolutionLevel: &zeroValue}
+	b.GetRequiredConversationResolutionLevel()
+	b = &BranchProtectionRule{}
+	b.GetRequiredConversationResolutionLevel()
+	b = nil
+	b.GetRequiredConversationResolutionLevel()
+}
+
+func TestBranchProtectionRule_GetRequiredDeploymentsEnforcementLevel(tt *testing.T) {
+	var zeroValue string
+	b := &BranchProtectionRule{RequiredDeploymentsEnforcementLevel: &zeroValue}
+	b.GetRequiredDeploymentsEnforcementLevel()
+	b = &BranchProtectionRule{}
+	b.GetRequiredDeploymentsEnforcementLevel()
+	b = nil
+	b.GetRequiredDeploymentsEnforcementLevel()
+}
+
+func TestBranchProtectionRule_GetRequiredStatusChecksEnforcementLevel(tt *testing.T) {
+	var zeroValue string
+	b := &BranchProtectionRule{RequiredStatusChecksEnforcementLevel: &zeroValue}
+	b.GetRequiredStatusChecksEnforcementLevel()
+	b = &BranchProtectionRule{}
+	b.GetRequiredStatusChecksEnforcementLevel()
+	b = nil
+	b.GetRequiredStatusChecksEnforcementLevel()
+}
+
+func TestBranchProtectionRule_GetSignatureRequirementEnforcementLevel(tt *testing.T) {
+	var zeroValue string
+	b := &BranchProtectionRule{SignatureRequirementEnforcementLevel: &zeroValue}
+	b.GetSignatureRequirementEnforcementLevel()
+	b = &BranchProtectionRule{}
+	b.GetSignatureRequirementEnforcementLevel()
+	b = nil
+	b.GetSignatureRequirementEnforcementLevel()
+}
+
+func TestBranchProtectionRule_GetStrictRequiredStatusChecksPolicy(tt *testing.T) {
+	var zeroValue bool
+	b := &BranchProtectionRule{StrictRequiredStatusChecksPolicy: &zeroValue}
+	b.GetStrictRequiredStatusChecksPolicy()
+	b = &BranchProtectionRule{}
+	b.GetStrictRequiredStatusChecksPolicy()
+	b = nil
+	b.GetStrictRequiredStatusChecksPolicy()
+}
+
+func TestBranchProtectionRule_GetUpdatedAt(tt *testing.T) {
+	var zeroValue Timestamp
+	b := &BranchProtectionRule{UpdatedAt: &zeroValue}
+	b.GetUpdatedAt()
+	b = &BranchProtectionRule{}
+	b.GetUpdatedAt()
+	b = nil
+	b.GetUpdatedAt()
+}
+
+func TestBranchProtectionRuleEvent_GetAction(tt *testing.T) {
+	var zeroValue string
+	b := &BranchProtectionRuleEvent{Action: &zeroValue}
+	b.GetAction()
+	b = &BranchProtectionRuleEvent{}
+	b.GetAction()
+	b = nil
+	b.GetAction()
+}
+
+func TestBranchProtectionRuleEvent_GetChanges(tt *testing.T) {
+	b := &BranchProtectionRuleEvent{}
+	b.GetChanges()
+	b = nil
+	b.GetChanges()
+}
+
+func TestBranchProtectionRuleEvent_GetOrg(tt *testing.T) {
+	b := &BranchProtectionRuleEvent{}
+	b.GetOrg()
+	b = nil
+	b.GetOrg()
+}
+
+func TestBranchProtectionRuleEvent_GetRepo(tt *testing.T) {
+	b := &BranchProtectionRuleEvent{}
+	b.GetRepo()
+	b = nil
+	b.GetRepo()
+}
+
+func TestBranchProtectionRuleEvent_GetRule(tt *testing.T) {
+	b := &BranchProtectionRuleEvent{}
+	b.GetRule()
+	b = nil
+	b.GetRule()
+}
+
+func TestBranchProtectionRuleEvent_GetSender(tt *testing.T) {
+	b := &BranchProtectionRuleEvent{}
+	b.GetSender()
+	b = nil
+	b.GetSender()
+}
+
 func TestCheckRun_GetApp(tt *testing.T) {
 	c := &CheckRun{}
 	c.GetApp()
@@ -3681,6 +3956,13 @@ func TestDeployKeyEvent_GetAction(tt *testing.T) {
 	d.GetAction()
 }
 
+func TestDeployKeyEvent_GetInstallation(tt *testing.T) {
+	d := &DeployKeyEvent{}
+	d.GetInstallation()
+	d = nil
+	d.GetInstallation()
+}
+
 func TestDeployKeyEvent_GetKey(tt *testing.T) {
 	d := &DeployKeyEvent{}
 	d.GetKey()
@@ -5391,6 +5673,13 @@ func TestGitHubAppAuthorizationEvent_GetAction(tt *testing.T) {
 	g.GetAction()
 }
 
+func TestGitHubAppAuthorizationEvent_GetInstallation(tt *testing.T) {
+	g := &GitHubAppAuthorizationEvent{}
+	g.GetInstallation()
+	g = nil
+	g.GetInstallation()
+}
+
 func TestGitHubAppAuthorizationEvent_GetSender(tt *testing.T) {
 	g := &GitHubAppAuthorizationEvent{}
 	g.GetSender()
@@ -5840,6 +6129,16 @@ func TestHookConfig_GetInsecureSSL(tt *testing.T) {
 	h.GetInsecureSSL()
 }
 
+func TestHookConfig_GetSecret(tt *testing.T) {
+	var zeroValue string
+	h := &HookConfig{Secret: &zeroValue}
+	h.GetSecret()
+	h = &HookConfig{}
+	h.GetSecret()
+	h = nil
+	h.GetSecret()
+}
+
 func TestHookConfig_GetURL(tt *testing.T) {
 	var zeroValue string
 	h := &HookConfig{URL: &zeroValue}
@@ -9134,6 +9433,13 @@ func TestMetaEvent_GetHookID(tt *testing.T) {
 	m.GetHookID()
 }
 
+func TestMetaEvent_GetInstallation(tt *testing.T) {
+	m := &MetaEvent{}
+	m.GetInstallation()
+	m = nil
+	m.GetInstallation()
+}
+
 func TestMetric_GetHTMLURL(tt *testing.T) {
 	var zeroValue string
 	m := &Metric{HTMLURL: &zeroValue}
@@ -10512,6 +10818,13 @@ func TestPackage_GetRegistry(tt *testing.T) {
 	p.GetRegistry()
 }
 
+func TestPackage_GetRepository(tt *testing.T) {
+	p := &Package{}
+	p.GetRepository()
+	p = nil
+	p.GetRepository()
+}
+
 func TestPackage_GetUpdatedAt(tt *testing.T) {
 	var zeroValue Timestamp
 	p := &Package{UpdatedAt: &zeroValue}
@@ -10522,6 +10835,36 @@ func TestPackage_GetUpdatedAt(tt *testing.T) {
 	p.GetUpdatedAt()
 }
 
+func TestPackage_GetURL(tt *testing.T) {
+	var zeroValue string
+	p := &Package{URL: &zeroValue}
+	p.GetURL()
+	p = &Package{}
+	p.GetURL()
+	p = nil
+	p.GetURL()
+}
+
+func TestPackage_GetVersionCount(tt *testing.T) {
+	var zeroValue int64
+	p := &Package{VersionCount: &zeroValue}
+	p.GetVersionCount()
+	p = &Package{}
+	p.GetVersionCount()
+	p = nil
+	p.GetVersionCount()
+}
+
+func TestPackage_GetVisibility(tt *testing.T) {
+	var zeroValue string
+	p := &Package{Visibility: &zeroValue}
+	p.GetVisibility()
+	p = &Package{}
+	p.GetVisibility()
+	p = nil
+	p.GetVisibility()
+}
+
 func TestPackageEvent_GetAction(tt *testing.T) {
 	var zeroValue string
 	p := &PackageEvent{Action: &zeroValue}
@@ -10532,6 +10875,13 @@ func TestPackageEvent_GetAction(tt *testing.T) {
 	p.GetAction()
 }
 
+func TestPackageEvent_GetInstallation(tt *testing.T) {
+	p := &PackageEvent{}
+	p.GetInstallation()
+	p = nil
+	p.GetInstallation()
+}
+
 func TestPackageEvent_GetOrg(tt *testing.T) {
 	p := &PackageEvent{}
 	p.GetOrg()
@@ -10677,6 +11027,53 @@ func TestPackageFile_GetUpdatedAt(tt *testing.T) {
 	p.GetUpdatedAt()
 }
 
+func TestPackageListOptions_GetPackageType(tt *testing.T) {
+	var zeroValue string
+	p := &PackageListOptions{PackageType: &zeroValue}
+	p.GetPackageType()
+	p = &PackageListOptions{}
+	p.GetPackageType()
+	p = nil
+	p.GetPackageType()
+}
+
+func TestPackageListOptions_GetState(tt *testing.T) {
+	var zeroValue string
+	p := &PackageListOptions{State: &zeroValue}
+	p.GetState()
+	p = &PackageListOptions{}
+	p.GetState()
+	p = nil
+	p.GetState()
+}
+
+func TestPackageListOptions_GetVisibility(tt *testing.T) {
+	var zeroValue string
+	p := &PackageListOptions{Visibility: &zeroValue}
+	p.GetVisibility()
+	p = &PackageListOptions{}
+	p.GetVisibility()
+	p = nil
+	p.GetVisibility()
+}
+
+func TestPackageMetadata_GetContainer(tt *testing.T) {
+	p := &PackageMetadata{}
+	p.GetContainer()
+	p = nil
+	p.GetContainer()
+}
+
+func TestPackageMetadata_GetPackageType(tt *testing.T) {
+	var zeroValue string
+	p := &PackageMetadata{PackageType: &zeroValue}
+	p.GetPackageType()
+	p = &PackageMetadata{}
+	p.GetPackageType()
+	p = nil
+	p.GetPackageType()
+}
+
 func TestPackageRegistry_GetAboutURL(tt *testing.T) {
 	var zeroValue string
 	p := &PackageRegistry{AboutURL: &zeroValue}
@@ -10921,6 +11318,33 @@ func TestPackageVersion_GetManifest(tt *testing.T) {
 	p.GetManifest()
 }
 
+func TestPackageVersion_GetMetadata(tt *testing.T) {
+	p := &PackageVersion{}
+	p.GetMetadata()
+	p = nil
+	p.GetMetadata()
+}
+
+func TestPackageVersion_GetName(tt *testing.T) {
+	var zeroValue string
+	p := &PackageVersion{Name: &zeroValue}
+	p.GetName()
+	p = &PackageVersion{}
+	p.GetName()
+	p = nil
+	p.GetName()
+}
+
+func TestPackageVersion_GetPackageHTMLURL(tt *testing.T) {
+	var zeroValue string
+	p := &PackageVersion{PackageHTMLURL: &zeroValue}
+	p.GetPackageHTMLURL()
+	p = &PackageVersion{}
+	p.GetPackageHTMLURL()
+	p = nil
+	p.GetPackageHTMLURL()
+}
+
 func TestPackageVersion_GetPrerelease(tt *testing.T) {
 	var zeroValue bool
 	p := &PackageVersion{Prerelease: &zeroValue}
@@ -10988,6 +11412,16 @@ func TestPackageVersion_GetUpdatedAt(tt *testing.T) {
 	p.GetUpdatedAt()
 }
 
+func TestPackageVersion_GetURL(tt *testing.T) {
+	var zeroValue string
+	p := &PackageVersion{URL: &zeroValue}
+	p.GetURL()
+	p = &PackageVersion{}
+	p.GetURL()
+	p = nil
+	p.GetURL()
+}
+
 func TestPackageVersion_GetVersion(tt *testing.T) {
 	var zeroValue string
 	p := &PackageVersion{Version: &zeroValue}
@@ -12238,6 +12672,20 @@ func TestProtection_GetRestrictions(tt *testing.T) {
 	p.GetRestrictions()
 }
 
+func TestProtectionChanges_GetAuthorizedActorNames(tt *testing.T) {
+	p := &ProtectionChanges{}
+	p.GetAuthorizedActorNames()
+	p = nil
+	p.GetAuthorizedActorNames()
+}
+
+func TestProtectionChanges_GetAuthorizedActorsOnly(tt *testing.T) {
+	p := &ProtectionChanges{}
+	p.GetAuthorizedActorsOnly()
+	p = nil
+	p.GetAuthorizedActorsOnly()
+}
+
 func TestProtectionRequest_GetAllowDeletions(tt *testing.T) {
 	var zeroValue bool
 	p := &ProtectionRequest{AllowDeletions: &zeroValue}
@@ -16699,6 +17147,13 @@ func TestRepositoryVulnerabilityAlertEvent_GetAlert(tt *testing.T) {
 	r.GetAlert()
 }
 
+func TestRepositoryVulnerabilityAlertEvent_GetInstallation(tt *testing.T) {
+	r := &RepositoryVulnerabilityAlertEvent{}
+	r.GetInstallation()
+	r = nil
+	r.GetInstallation()
+}
+
 func TestRepositoryVulnerabilityAlertEvent_GetRepository(tt *testing.T) {
 	r := &RepositoryVulnerabilityAlertEvent{}
 	r.GetRepository()
@@ -17457,6 +17912,13 @@ func TestStarEvent_GetAction(tt *testing.T) {
 	s.GetAction()
 }
 
+func TestStarEvent_GetInstallation(tt *testing.T) {
+	s := &StarEvent{}
+	s.GetInstallation()
+	s = nil
+	s.GetInstallation()
+}
+
 func TestStarEvent_GetOrg(tt *testing.T) {
 	s := &StarEvent{}
 	s.GetOrg()
@@ -19752,6 +20214,13 @@ func TestUserEvent_GetEnterprise(tt *testing.T) {
 	u.GetEnterprise()
 }
 
+func TestUserEvent_GetInstallation(tt *testing.T) {
+	u := &UserEvent{}
+	u.GetInstallation()
+	u = nil
+	u.GetInstallation()
+}
+
 func TestUserEvent_GetSender(tt *testing.T) {
 	u := &UserEvent{}
 	u.GetSender()
@@ -20483,6 +20952,13 @@ func TestWorkflowBill_GetTotalMS(tt *testing.T) {
 	w.GetTotalMS()
 }
 
+func TestWorkflowDispatchEvent_GetInstallation(tt *testing.T) {
+	w := &WorkflowDispatchEvent{}
+	w.GetInstallation()
+	w = nil
+	w.GetInstallation()
+}
+
 func TestWorkflowDispatchEvent_GetOrg(tt *testing.T) {
 	w := &WorkflowDispatchEvent{}
 	w.GetOrg()
@@ -20685,6 +21161,13 @@ func TestWorkflowJobEvent_GetAction(tt *testing.T) {
 	w.GetAction()
 }
 
+func TestWorkflowJobEvent_GetInstallation(tt *testing.T) {
+	w := &WorkflowJobEvent{}
+	w.GetInstallation()
+	w = nil
+	w.GetInstallation()
+}
+
 func TestWorkflowJobEvent_GetOrg(tt *testing.T) {
 	w := &WorkflowJobEvent{}
 	w.GetOrg()
@@ -20733,6 +21216,26 @@ func TestWorkflowRun_GetCancelURL(tt *testing.T) {
 	w.GetCancelURL()
 }
 
+func TestWorkflowRun_GetCheckSuiteID(tt *testing.T) {
+	var zeroValue int64
+	w := &WorkflowRun{CheckSuiteID: &zeroValue}
+	w.GetCheckSuiteID()
+	w = &WorkflowRun{}
+	w.GetCheckSuiteID()
+	w = nil
+	w.GetCheckSuiteID()
+}
+
+func TestWorkflowRun_GetCheckSuiteNodeID(tt *testing.T) {
+	var zeroValue string
+	w := &WorkflowRun{CheckSuiteNodeID: &zeroValue}
+	w.GetCheckSuiteNodeID()
+	w = &WorkflowRun{}
+	w.GetCheckSuiteNodeID()
+	w = nil
+	w.GetCheckSuiteNodeID()
+}
+
 func TestWorkflowRun_GetCheckSuiteURL(tt *testing.T) {
 	var zeroValue string
 	w := &WorkflowRun{CheckSuiteURL: &zeroValue}
@@ -20995,6 +21498,13 @@ func TestWorkflowRunEvent_GetAction(tt *testing.T) {
 	w.GetAction()
 }
 
+func TestWorkflowRunEvent_GetInstallation(tt *testing.T) {
+	w := &WorkflowRunEvent{}
+	w.GetInstallation()
+	w = nil
+	w.GetInstallation()
+}
+
 func TestWorkflowRunEvent_GetOrg(tt *testing.T) {
 	w := &WorkflowRunEvent{}
 	w.GetOrg()
diff --git a/github/github-stringify_test.go b/github/github-stringify_test.go
index f3cab123..19334ea1 100644
--- a/github/github-stringify_test.go
+++ b/github/github-stringify_test.go
@@ -969,8 +969,12 @@ func TestPackage_String(t *testing.T) {
 		Owner:          &User{},
 		PackageVersion: &PackageVersion{},
 		Registry:       &PackageRegistry{},
+		URL:            String(""),
+		VersionCount:   Int64(0),
+		Visibility:     String(""),
+		Repository:     &Repository{},
 	}
-	want := `github.Package{ID:0, Name:"", PackageType:"", HTMLURL:"", CreatedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, UpdatedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, Owner:github.User{}, PackageVersion:github.PackageVersion{}, Registry:github.PackageRegistry{}}`
+	want := `github.Package{ID:0, Name:"", PackageType:"", HTMLURL:"", CreatedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, UpdatedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, Owner:github.User{}, PackageVersion:github.PackageVersion{}, Registry:github.PackageRegistry{}, URL:"", VersionCount:0, Visibility:"", Repository:github.Repository{}}`
 	if got := v.String(); got != want {
 		t.Errorf("Package.String = %v, want %v", got, want)
 	}
@@ -997,6 +1001,17 @@ func TestPackageFile_String(t *testing.T) {
 	}
 }
 
+func TestPackageMetadata_String(t *testing.T) {
+	v := PackageMetadata{
+		PackageType: String(""),
+		Container:   &PackageContainerMetadata{},
+	}
+	want := `github.PackageMetadata{PackageType:"", Container:github.PackageContainerMetadata{}}`
+	if got := v.String(); got != want {
+		t.Errorf("PackageMetadata.String = %v, want %v", got, want)
+	}
+}
+
 func TestPackageRegistry_String(t *testing.T) {
 	v := PackageRegistry{
 		AboutURL: String(""),
@@ -1050,8 +1065,12 @@ func TestPackageVersion_String(t *testing.T) {
 		UpdatedAt:           &Timestamp{},
 		Author:              &User{},
 		InstallationCommand: String(""),
+		Metadata:            &PackageMetadata{},
+		PackageHTMLURL:      String(""),
+		Name:                String(""),
+		URL:                 String(""),
 	}
-	want := `github.PackageVersion{ID:0, Version:"", Summary:"", Body:"", BodyHTML:"", Release:github.PackageRelease{}, Manifest:"", HTMLURL:"", TagName:"", TargetCommitish:"", TargetOID:"", Draft:false, Prerelease:false, CreatedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, UpdatedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, Author:github.User{}, InstallationCommand:""}`
+	want := `github.PackageVersion{ID:0, Version:"", Summary:"", Body:"", BodyHTML:"", Release:github.PackageRelease{}, Manifest:"", HTMLURL:"", TagName:"", TargetCommitish:"", TargetOID:"", Draft:false, Prerelease:false, CreatedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, UpdatedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, Author:github.User{}, InstallationCommand:"", Metadata:github.PackageMetadata{}, PackageHTMLURL:"", Name:"", URL:""}`
 	if got := v.String(); got != want {
 		t.Errorf("PackageVersion.String = %v, want %v", got, want)
 	}
diff --git a/github/github_test.go b/github/github_test.go
index e92dbb66..08d2c8ad 100644
--- a/github/github_test.go
+++ b/github/github_test.go
@@ -1229,7 +1229,7 @@ func TestCompareHttpResponse(t *testing.T) {
 
 	for name, tc := range testcases {
 		t.Run(name, func(t *testing.T) {
-			v := compareHttpResponse(tc.h1, tc.h2)
+			v := compareHTTPResponse(tc.h1, tc.h2)
 			if tc.expected != v {
 				t.Errorf("Expected %t, got %t for (%#v, %#v)", tc.expected, v, tc.h1, tc.h2)
 			}
@@ -2028,7 +2028,6 @@ func TestAddOptions_QueryValues(t *testing.T) {
 }
 
 func TestBareDo_returnsOpenBody(t *testing.T) {
-
 	client, mux, _, teardown := setup()
 	defer teardown()
 
diff --git a/github/messages_test.go b/github/messages_test.go
index da8c3331..491cbbaf 100644
--- a/github/messages_test.go
+++ b/github/messages_test.go
@@ -261,6 +261,10 @@ func TestParseWebHook(t *testing.T) {
 		payload     interface{}
 		messageType string
 	}{
+		{
+			payload:     &BranchProtectionRuleEvent{},
+			messageType: "branch_protection_rule",
+		},
 		{
 			payload:     &CheckRunEvent{},
 			messageType: "check_run",
diff --git a/github/orgs_audit_log_test.go b/github/orgs_audit_log_test.go
index 1121ffd2..95b0a0cf 100644
--- a/github/orgs_audit_log_test.go
+++ b/github/orgs_audit_log_test.go
@@ -110,7 +110,6 @@ func TestOrganizationService_GetAuditLog(t *testing.T) {
 		}
 		return resp, err
 	})
-
 }
 
 func TestGetAuditLogOptions_Marshal(t *testing.T) {
diff --git a/github/orgs_members_test.go b/github/orgs_members_test.go
index 442ae13e..adc14f5b 100644
--- a/github/orgs_members_test.go
+++ b/github/orgs_members_test.go
@@ -655,7 +655,6 @@ func TestOrganizationsService_CreateOrgInvitation(t *testing.T) {
 		}
 
 		fmt.Fprintln(w, `{"email": "octocat@github.com"}`)
-
 	})
 
 	ctx := context.Background()
diff --git a/github/orgs_packages_test.go b/github/orgs_packages_test.go
new file mode 100644
index 00000000..bbe223b8
--- /dev/null
+++ b/github/orgs_packages_test.go
@@ -0,0 +1,406 @@
+// Copyright 2021 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.
+
+package github
+
+import (
+	"context"
+	"fmt"
+	"net/http"
+	"testing"
+
+	"github.com/google/go-cmp/cmp"
+)
+
+func TestOrganizationsService_ListPackages(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/orgs/o/packages", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "GET")
+		fmt.Fprint(w, `[{
+			"id": 197,
+			"name": "hello_docker",
+			"package_type": "container",
+			"owner": {
+			  "login": "github",
+			  "id": 9919,
+			  "node_id": "MDEyOk9yZ2FuaXphdGlvbjk5MTk=",
+			  "avatar_url": "https://avatars.githubusercontent.com/u/9919?v=4",
+			  "gravatar_id": "",
+			  "url": "https://api.github.com/users/github",
+			  "html_url": "https://github.com/github",
+			  "followers_url": "https://api.github.com/users/github/followers",
+			  "following_url": "https://api.github.com/users/github/following{/other_user}",
+			  "gists_url": "https://api.github.com/users/github/gists{/gist_id}",
+			  "starred_url": "https://api.github.com/users/github/starred{/owner}{/repo}",
+			  "subscriptions_url": "https://api.github.com/users/github/subscriptions",
+			  "organizations_url": "https://api.github.com/users/github/orgs",
+			  "repos_url": "https://api.github.com/users/github/repos",
+			  "events_url": "https://api.github.com/users/github/events{/privacy}",
+			  "received_events_url": "https://api.github.com/users/github/received_events",
+			  "type": "Organization",
+			  "site_admin": false
+			},
+			"version_count": 1,
+			"visibility": "private",
+			"url": "https://api.github.com/orgs/github/packages/container/hello_docker",
+			"created_at": `+referenceTimeStr+`,
+			"updated_at": `+referenceTimeStr+`,
+			"html_url": "https://github.com/orgs/github/packages/container/package/hello_docker"
+		  }
+		  ]`)
+	})
+
+	ctx := context.Background()
+	packages, _, err := client.Organizations.ListPackages(ctx, "o", &PackageListOptions{})
+	if err != nil {
+		t.Errorf("Organizations.ListPackages returned error: %v", err)
+	}
+
+	want := []*Package{{
+		ID:           Int64(197),
+		Name:         String("hello_docker"),
+		PackageType:  String("container"),
+		VersionCount: Int64(1),
+		Visibility:   String("private"),
+		URL:          String("https://api.github.com/orgs/github/packages/container/hello_docker"),
+		HTMLURL:      String("https://github.com/orgs/github/packages/container/package/hello_docker"),
+		CreatedAt:    &Timestamp{referenceTime},
+		UpdatedAt:    &Timestamp{referenceTime},
+		Owner: &User{
+			Login:             String("github"),
+			ID:                Int64(9919),
+			NodeID:            String("MDEyOk9yZ2FuaXphdGlvbjk5MTk="),
+			AvatarURL:         String("https://avatars.githubusercontent.com/u/9919?v=4"),
+			GravatarID:        String(""),
+			URL:               String("https://api.github.com/users/github"),
+			HTMLURL:           String("https://github.com/github"),
+			FollowersURL:      String("https://api.github.com/users/github/followers"),
+			FollowingURL:      String("https://api.github.com/users/github/following{/other_user}"),
+			GistsURL:          String("https://api.github.com/users/github/gists{/gist_id}"),
+			StarredURL:        String("https://api.github.com/users/github/starred{/owner}{/repo}"),
+			SubscriptionsURL:  String("https://api.github.com/users/github/subscriptions"),
+			OrganizationsURL:  String("https://api.github.com/users/github/orgs"),
+			ReposURL:          String("https://api.github.com/users/github/repos"),
+			EventsURL:         String("https://api.github.com/users/github/events{/privacy}"),
+			ReceivedEventsURL: String("https://api.github.com/users/github/received_events"),
+			Type:              String("Organization"),
+			SiteAdmin:         Bool(false),
+		},
+	}}
+	if !cmp.Equal(packages, want) {
+		t.Errorf("Organizations.ListPackages returned %+v, want %+v", packages, want)
+	}
+
+	const methodName = "ListPackages"
+	testBadOptions(t, methodName, func() (err error) {
+		_, _, err = client.Organizations.ListPackages(ctx, "\n", &PackageListOptions{})
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		got, resp, err := client.Organizations.ListPackages(ctx, "o", &PackageListOptions{})
+		if got != nil {
+			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+		}
+		return resp, err
+	})
+}
+
+func TestOrganizationsService_GetPackage(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/orgs/o/packages/container/hello_docker", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "GET")
+		fmt.Fprint(w, `{
+			"id": 197,
+			"name": "hello_docker",
+			"package_type": "container",
+			"version_count": 1,
+			"visibility": "private",
+			"url": "https://api.github.com/orgs/github/packages/container/hello_docker",
+			"created_at": `+referenceTimeStr+`,
+			"updated_at": `+referenceTimeStr+`,
+			"html_url": "https://github.com/orgs/github/packages/container/package/hello_docker"
+		  }`)
+	})
+
+	ctx := context.Background()
+	packages, _, err := client.Organizations.GetPackage(ctx, "o", "container", "hello_docker")
+	if err != nil {
+		t.Errorf("Organizations.GetPackage returned error: %v", err)
+	}
+
+	want := &Package{
+		ID:           Int64(197),
+		Name:         String("hello_docker"),
+		PackageType:  String("container"),
+		VersionCount: Int64(1),
+		Visibility:   String("private"),
+		URL:          String("https://api.github.com/orgs/github/packages/container/hello_docker"),
+		HTMLURL:      String("https://github.com/orgs/github/packages/container/package/hello_docker"),
+		CreatedAt:    &Timestamp{referenceTime},
+		UpdatedAt:    &Timestamp{referenceTime},
+	}
+	if !cmp.Equal(packages, want) {
+		t.Errorf("Organizations.GetPackage returned %+v, want %+v", packages, want)
+	}
+
+	const methodName = "GetPackage"
+	testBadOptions(t, methodName, func() (err error) {
+		_, _, err = client.Organizations.GetPackage(ctx, "\n", "", "")
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		got, resp, err := client.Organizations.GetPackage(ctx, "", "", "")
+		if got != nil {
+			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+		}
+		return resp, err
+	})
+}
+
+func TestOrganizationsService_DeletePackage(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/orgs/o/packages/container/hello_docker", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "DELETE")
+	})
+
+	ctx := context.Background()
+	_, err := client.Organizations.DeletePackage(ctx, "o", "container", "hello_docker")
+	if err != nil {
+		t.Errorf("Organizations.DeletePackage returned error: %v", err)
+	}
+
+	const methodName = "DeletePackage"
+	testBadOptions(t, methodName, func() (err error) {
+		_, _, err = client.Organizations.GetPackage(ctx, "\n", "", "")
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		got, resp, err := client.Organizations.GetPackage(ctx, "", "", "")
+		if got != nil {
+			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+		}
+		return resp, err
+	})
+}
+
+func TestOrganizationsService_RestorePackage(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/orgs/o/packages/container/hello_docker/restore", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "POST")
+	})
+
+	ctx := context.Background()
+	_, err := client.Organizations.RestorePackage(ctx, "o", "container", "hello_docker")
+	if err != nil {
+		t.Errorf("Organizations.RestorePackage returned error: %v", err)
+	}
+
+	const methodName = "RestorePackage"
+	testBadOptions(t, methodName, func() (err error) {
+		_, err = client.Organizations.RestorePackage(ctx, "\n", "", "")
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		return client.Organizations.RestorePackage(ctx, "", "container", "hello_docker")
+	})
+}
+
+func TestOrganizationsService_ListPackagesVersions(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/orgs/o/packages/container/hello_docker/versions", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "GET")
+		testFormValues(t, r, values{"per_page": "2", "page": "1", "state": "deleted", "visibility": "internal", "package_type": "container"})
+		fmt.Fprint(w, `[
+			{
+			  "id": 45763,
+			  "name": "sha256:08a44bab0bddaddd8837a8b381aebc2e4b933768b981685a9e088360af0d3dd9",
+			  "url": "https://api.github.com/users/octocat/packages/container/hello_docker/versions/45763",
+			  "package_html_url": "https://github.com/users/octocat/packages/container/package/hello_docker",
+			  "created_at": `+referenceTimeStr+`,
+			  "updated_at": `+referenceTimeStr+`,
+			  "html_url": "https://github.com/users/octocat/packages/container/hello_docker/45763",
+			  "metadata": {
+				"package_type": "container",
+				"container": {
+				  "tags": [
+					"latest"
+				  ]
+				}
+			  }
+			}]`)
+	})
+
+	ctx := context.Background()
+	opts := &PackageListOptions{
+		String("internal"), String("container"), String("deleted"), ListOptions{Page: 1, PerPage: 2},
+	}
+	packages, _, err := client.Organizations.PackageGetAllVersions(ctx, "o", "container", "hello_docker", opts)
+	if err != nil {
+		t.Errorf("Organizations.PackageGetAllVersions returned error: %v", err)
+	}
+
+	want := []*PackageVersion{{
+		ID:             Int64(45763),
+		Name:           String("sha256:08a44bab0bddaddd8837a8b381aebc2e4b933768b981685a9e088360af0d3dd9"),
+		URL:            String("https://api.github.com/users/octocat/packages/container/hello_docker/versions/45763"),
+		PackageHTMLURL: String("https://github.com/users/octocat/packages/container/package/hello_docker"),
+		CreatedAt:      &Timestamp{referenceTime},
+		UpdatedAt:      &Timestamp{referenceTime},
+		HTMLURL:        String("https://github.com/users/octocat/packages/container/hello_docker/45763"),
+		Metadata: &PackageMetadata{
+			PackageType: String("container"),
+			Container: &PackageContainerMetadata{
+				Tags: []string{"latest"},
+			},
+		},
+	}}
+	if !cmp.Equal(packages, want) {
+		t.Errorf("Organizations.PackageGetAllVersions returned %+v, want %+v", packages, want)
+	}
+
+	const methodName = "PackageGetAllVersions"
+	testBadOptions(t, methodName, func() (err error) {
+		_, _, err = client.Organizations.PackageGetAllVersions(ctx, "\n", "", "", &PackageListOptions{})
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		got, resp, err := client.Organizations.PackageGetAllVersions(ctx, "", "", "", &PackageListOptions{})
+		if got != nil {
+			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+		}
+		return resp, err
+	})
+}
+
+func TestOrganizationsService_PackageGetVersion(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/orgs/o/packages/container/hello_docker/versions/45763", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "GET")
+		fmt.Fprint(w, `
+			{
+			  "id": 45763,
+			  "name": "sha256:08a44bab0bddaddd8837a8b381aebc2e4b933768b981685a9e088360af0d3dd9",
+			  "url": "https://api.github.com/users/octocat/packages/container/hello_docker/versions/45763",
+			  "package_html_url": "https://github.com/users/octocat/packages/container/package/hello_docker",
+			  "created_at": `+referenceTimeStr+`,
+			  "updated_at": `+referenceTimeStr+`,
+			  "html_url": "https://github.com/users/octocat/packages/container/hello_docker/45763",
+			  "metadata": {
+				"package_type": "container",
+				"container": {
+				  "tags": [
+					"latest"
+				  ]
+				}
+			  }
+			}`)
+	})
+
+	ctx := context.Background()
+	packages, _, err := client.Organizations.PackageGetVersion(ctx, "o", "container", "hello_docker", 45763)
+	if err != nil {
+		t.Errorf("Organizations.PackageGetVersion returned error: %v", err)
+	}
+
+	want := &PackageVersion{
+		ID:             Int64(45763),
+		Name:           String("sha256:08a44bab0bddaddd8837a8b381aebc2e4b933768b981685a9e088360af0d3dd9"),
+		URL:            String("https://api.github.com/users/octocat/packages/container/hello_docker/versions/45763"),
+		PackageHTMLURL: String("https://github.com/users/octocat/packages/container/package/hello_docker"),
+		CreatedAt:      &Timestamp{referenceTime},
+		UpdatedAt:      &Timestamp{referenceTime},
+		HTMLURL:        String("https://github.com/users/octocat/packages/container/hello_docker/45763"),
+		Metadata: &PackageMetadata{
+			PackageType: String("container"),
+			Container: &PackageContainerMetadata{
+				Tags: []string{"latest"},
+			},
+		},
+	}
+	if !cmp.Equal(packages, want) {
+		t.Errorf("Organizations.PackageGetVersion returned %+v, want %+v", packages, want)
+	}
+
+	const methodName = "PackageGetVersion"
+	testBadOptions(t, methodName, func() (err error) {
+		_, _, err = client.Organizations.PackageGetVersion(ctx, "\n", "", "", 0)
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		got, resp, err := client.Organizations.PackageGetVersion(ctx, "", "", "", 45763)
+		if got != nil {
+			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+		}
+		return resp, err
+	})
+}
+
+func TestOrganizationsService_PackageDeleteVersion(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/orgs/o/packages/container/hello_docker/versions/45763", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "DELETE")
+	})
+
+	ctx := context.Background()
+	_, err := client.Organizations.PackageDeleteVersion(ctx, "o", "container", "hello_docker", 45763)
+	if err != nil {
+		t.Errorf("Organizations.PackageDeleteVersion returned error: %v", err)
+	}
+
+	const methodName = "PackageDeleteVersion"
+	testBadOptions(t, methodName, func() (err error) {
+		_, err = client.Organizations.PackageDeleteVersion(ctx, "\n", "", "", 0)
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		return client.Organizations.PackageDeleteVersion(ctx, "", "", "", 45763)
+	})
+}
+
+func TestOrganizationsService_PackageRestoreVersion(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/orgs/o/packages/container/hello_docker/versions/45763/restore", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "POST")
+	})
+
+	ctx := context.Background()
+	_, err := client.Organizations.PackageRestoreVersion(ctx, "o", "container", "hello_docker", 45763)
+	if err != nil {
+		t.Errorf("Organizations.PackageRestoreVersion returned error: %v", err)
+	}
+
+	const methodName = "PackageRestoreVersion"
+	testBadOptions(t, methodName, func() (err error) {
+		_, err = client.Organizations.PackageRestoreVersion(ctx, "\n", "", "", 0)
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		return client.Organizations.PackageRestoreVersion(ctx, "", "", "", 45763)
+	})
+}
diff --git a/github/orgs_test.go b/github/orgs_test.go
index fe34a5a0..b30c48f1 100644
--- a/github/orgs_test.go
+++ b/github/orgs_test.go
@@ -357,7 +357,6 @@ func TestOrganizationsService_ListInstallations_invalidOrg(t *testing.T) {
 	ctx := context.Background()
 	_, _, err := client.Organizations.ListInstallations(ctx, "%", nil)
 	testURLParseError(t, err)
-
 }
 
 func TestOrganizationsService_ListInstallations_withListOptions(t *testing.T) {
diff --git a/github/packages_test.go b/github/packages_test.go
index 7d287d89..c825e6a5 100644
--- a/github/packages_test.go
+++ b/github/packages_test.go
@@ -400,6 +400,7 @@ func TestPackage_Marshal(t *testing.T) {
 		HTMLURL:     String("hurl"),
 		CreatedAt:   &Timestamp{referenceTime},
 		UpdatedAt:   &Timestamp{referenceTime},
+		Visibility:  String("private"),
 		Owner: &User{
 			Login:           String("l"),
 			ID:              Int64(1),
@@ -540,6 +541,7 @@ func TestPackage_Marshal(t *testing.T) {
 		"html_url": "hurl",
 		"created_at": ` + referenceTimeStr + `,
 		"updated_at": ` + referenceTimeStr + `,
+		"visibility": "private",
 		"owner": {
 			"login": "l",
 			"id": 1,
diff --git a/github/repos_test.go b/github/repos_test.go
index 4bb6be22..4c799048 100644
--- a/github/repos_test.go
+++ b/github/repos_test.go
@@ -1090,7 +1090,6 @@ func TestRepositoriesService_GetBranchProtection_noDismissalRestrictions(t *test
 	defer teardown()
 
 	mux.HandleFunc("/repos/o/r/branches/b/protection", func(w http.ResponseWriter, r *http.Request) {
-
 		testMethod(t, r, "GET")
 		// TODO: remove custom Accept header when this API fully launches
 		testHeader(t, r, "Accept", mediaTypeRequiredApprovingReviewsPreview)
@@ -2319,8 +2318,8 @@ func TestRepositoriesService_Dispatch(t *testing.T) {
 			Baz: false,
 		},
 	}
-	for _, tc := range testCases {
 
+	for _, tc := range testCases {
 		if tc == nil {
 			input = DispatchRequestOptions{EventType: "go"}
 		} else {
diff --git a/github/users_packages_test.go b/github/users_packages_test.go
new file mode 100644
index 00000000..5be7def1
--- /dev/null
+++ b/github/users_packages_test.go
@@ -0,0 +1,701 @@
+// Copyright 2021 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.
+
+package github
+
+import (
+	"context"
+	"fmt"
+	"net/http"
+	"testing"
+
+	"github.com/google/go-cmp/cmp"
+)
+
+func TestUsersService_Authenticated_ListPackages(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/user/packages", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "GET")
+		testFormValues(t, r, values{"package_type": "container", "visibility": "private"})
+		fmt.Fprint(w, `[{
+			"id": 197,
+			"name": "hello_docker",
+			"package_type": "container",
+			"version_count": 1,
+			"visibility": "private",
+			"url": "https://api.github.com/orgs/github/packages/container/hello_docker",
+			"created_at": `+referenceTimeStr+`,
+			"updated_at": `+referenceTimeStr+`,
+			"html_url": "https://github.com/orgs/github/packages/container/package/hello_docker"
+		  }]`)
+	})
+
+	ctx := context.Background()
+	packages, _, err := client.Users.ListPackages(ctx, "", &PackageListOptions{PackageType: String("container"), Visibility: String("private")})
+	if err != nil {
+		t.Errorf("Users.Authenticated_ListPackages returned error: %v", err)
+	}
+
+	want := []*Package{{
+		ID:           Int64(197),
+		Name:         String("hello_docker"),
+		PackageType:  String("container"),
+		VersionCount: Int64(1),
+		Visibility:   String("private"),
+		URL:          String("https://api.github.com/orgs/github/packages/container/hello_docker"),
+		HTMLURL:      String("https://github.com/orgs/github/packages/container/package/hello_docker"),
+		CreatedAt:    &Timestamp{referenceTime},
+		UpdatedAt:    &Timestamp{referenceTime},
+	}}
+	if !cmp.Equal(packages, want) {
+		t.Errorf("Users.Authenticated_ListPackages returned %+v, want %+v", packages, want)
+	}
+
+	const methodName = "ListPackages"
+	testBadOptions(t, methodName, func() (err error) {
+		_, _, err = client.Users.ListPackages(ctx, "\n", &PackageListOptions{})
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		got, resp, err := client.Users.ListPackages(ctx, "", &PackageListOptions{})
+		if got != nil {
+			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+		}
+		return resp, err
+	})
+}
+
+func TestUsersService_specifiedUser_ListPackages(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/user/u/packages", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "GET")
+		testFormValues(t, r, values{"package_type": "container", "visibility": "public"})
+		fmt.Fprint(w, `[{
+			"id": 197,
+			"name": "hello_docker",
+			"package_type": "container",
+			"version_count": 1,
+			"visibility": "public",
+			"url": "https://api.github.com/orgs/github/packages/container/hello_docker",
+			"created_at": `+referenceTimeStr+`,
+			"updated_at": `+referenceTimeStr+`,
+			"html_url": "https://github.com/orgs/github/packages/container/package/hello_docker"
+		  }]`)
+	})
+
+	ctx := context.Background()
+	packages, _, err := client.Users.ListPackages(ctx, "u", &PackageListOptions{PackageType: String("container"), Visibility: String("public")})
+	if err != nil {
+		t.Errorf("Users.specifiedUser_ListPackages returned error: %v", err)
+	}
+
+	want := []*Package{{
+		ID:           Int64(197),
+		Name:         String("hello_docker"),
+		PackageType:  String("container"),
+		VersionCount: Int64(1),
+		Visibility:   String("public"),
+		URL:          String("https://api.github.com/orgs/github/packages/container/hello_docker"),
+		HTMLURL:      String("https://github.com/orgs/github/packages/container/package/hello_docker"),
+		CreatedAt:    &Timestamp{referenceTime},
+		UpdatedAt:    &Timestamp{referenceTime},
+	}}
+	if !cmp.Equal(packages, want) {
+		t.Errorf("Users.specifiedUser_ListPackages returned %+v, want %+v", packages, want)
+	}
+
+	const methodName = "ListPackages"
+	testBadOptions(t, methodName, func() (err error) {
+		_, _, err = client.Users.ListPackages(ctx, "\n", &PackageListOptions{})
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		got, resp, err := client.Users.ListPackages(ctx, "", &PackageListOptions{})
+		if got != nil {
+			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+		}
+		return resp, err
+	})
+}
+
+func TestUsersService_specifiedUser_GetPackage(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/users/u/packages/container/hello_docker", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "GET")
+		fmt.Fprint(w, `{
+			"id": 197,
+			"name": "hello_docker",
+			"package_type": "container",
+			"version_count": 1,
+			"visibility": "private",
+			"url": "https://api.github.com/orgs/github/packages/container/hello_docker",
+			"created_at": `+referenceTimeStr+`,
+			"updated_at": `+referenceTimeStr+`,
+			"html_url": "https://github.com/orgs/github/packages/container/package/hello_docker"
+		  }`)
+	})
+
+	ctx := context.Background()
+	packages, _, err := client.Users.GetPackage(ctx, "u", "container", "hello_docker")
+	if err != nil {
+		t.Errorf("Users.GetPackage returned error: %v", err)
+	}
+
+	want := &Package{
+		ID:           Int64(197),
+		Name:         String("hello_docker"),
+		PackageType:  String("container"),
+		VersionCount: Int64(1),
+		Visibility:   String("private"),
+		URL:          String("https://api.github.com/orgs/github/packages/container/hello_docker"),
+		HTMLURL:      String("https://github.com/orgs/github/packages/container/package/hello_docker"),
+		CreatedAt:    &Timestamp{referenceTime},
+		UpdatedAt:    &Timestamp{referenceTime},
+	}
+	if !cmp.Equal(packages, want) {
+		t.Errorf("Users.specifiedUser_GetPackage returned %+v, want %+v", packages, want)
+	}
+
+	const methodName = "GetPackage"
+	testBadOptions(t, methodName, func() (err error) {
+		_, _, err = client.Users.GetPackage(ctx, "\n", "\n", "\n")
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		got, resp, err := client.Users.GetPackage(ctx, "", "", "")
+		if got != nil {
+			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+		}
+		return resp, err
+	})
+}
+
+func TestUsersService_Authenticated_GetPackage(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/user/packages/container/hello_docker", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "GET")
+		fmt.Fprint(w, `{
+			"id": 197,
+			"name": "hello_docker",
+			"package_type": "container",
+			"version_count": 1,
+			"visibility": "private",
+			"url": "https://api.github.com/orgs/github/packages/container/hello_docker",
+			"created_at": `+referenceTimeStr+`,
+			"updated_at": `+referenceTimeStr+`,
+			"html_url": "https://github.com/orgs/github/packages/container/package/hello_docker"
+		  }`)
+	})
+
+	ctx := context.Background()
+	packages, _, err := client.Users.GetPackage(ctx, "", "container", "hello_docker")
+	if err != nil {
+		t.Errorf("Users.Authenticated_GetPackage returned error: %v", err)
+	}
+
+	want := &Package{
+		ID:           Int64(197),
+		Name:         String("hello_docker"),
+		PackageType:  String("container"),
+		VersionCount: Int64(1),
+		Visibility:   String("private"),
+		URL:          String("https://api.github.com/orgs/github/packages/container/hello_docker"),
+		HTMLURL:      String("https://github.com/orgs/github/packages/container/package/hello_docker"),
+		CreatedAt:    &Timestamp{referenceTime},
+		UpdatedAt:    &Timestamp{referenceTime},
+	}
+	if !cmp.Equal(packages, want) {
+		t.Errorf("Users.Authenticated_GetPackage returned %+v, want %+v", packages, want)
+	}
+
+	const methodName = "GetPackage"
+	testBadOptions(t, methodName, func() (err error) {
+		_, _, err = client.Users.GetPackage(ctx, "\n", "\n", "\n")
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		got, resp, err := client.Users.GetPackage(ctx, "", "", "")
+		if got != nil {
+			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+		}
+		return resp, err
+	})
+}
+
+func TestUsersService_Authenticated_DeletePackage(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/user/packages/container/hello_docker", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "DELETE")
+	})
+
+	ctx := context.Background()
+	_, err := client.Users.DeletePackage(ctx, "", "container", "hello_docker")
+	if err != nil {
+		t.Errorf("Users.Authenticated_DeletePackage returned error: %v", err)
+	}
+
+	const methodName = "DeletePackage"
+	testBadOptions(t, methodName, func() (err error) {
+		_, err = client.Users.DeletePackage(ctx, "\n", "\n", "\n")
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		return client.Users.DeletePackage(ctx, "", "", "")
+	})
+}
+
+func TestUsersService_specifiedUser_DeletePackage(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/users/u/packages/container/hello_docker", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "DELETE")
+	})
+
+	ctx := context.Background()
+	_, err := client.Users.DeletePackage(ctx, "u", "container", "hello_docker")
+	if err != nil {
+		t.Errorf("Users.specifiedUser_DeletePackage returned error: %v", err)
+	}
+
+	const methodName = "DeletePackage"
+	testBadOptions(t, methodName, func() (err error) {
+		_, err = client.Users.DeletePackage(ctx, "\n", "\n", "\n")
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		return client.Users.DeletePackage(ctx, "", "", "")
+	})
+}
+
+func TestUsersService_Authenticated_RestorePackage(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/user/packages/container/hello_docker/restore", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "POST")
+	})
+
+	ctx := context.Background()
+	_, err := client.Users.RestorePackage(ctx, "", "container", "hello_docker")
+	if err != nil {
+		t.Errorf("Users.Authenticated_RestorePackage returned error: %v", err)
+	}
+
+	const methodName = "RestorePackage"
+	testBadOptions(t, methodName, func() (err error) {
+		_, err = client.Users.RestorePackage(ctx, "\n", "", "")
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		return client.Users.RestorePackage(ctx, "", "container", "hello_docker")
+	})
+}
+
+func TestUsersService_specifiedUser_RestorePackage(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/users/u/packages/container/hello_docker/restore", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "POST")
+	})
+
+	ctx := context.Background()
+	_, err := client.Users.RestorePackage(ctx, "u", "container", "hello_docker")
+	if err != nil {
+		t.Errorf("Users.specifiedUser_RestorePackage returned error: %v", err)
+	}
+
+	const methodName = "RestorePackage"
+	testBadOptions(t, methodName, func() (err error) {
+		_, err = client.Users.RestorePackage(ctx, "\n", "", "")
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		return client.Users.RestorePackage(ctx, "", "container", "hello_docker")
+	})
+}
+
+func TestUsersService_Authenticated_ListPackagesVersions(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/user/packages/container/hello_docker/versions", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "GET")
+		fmt.Fprint(w, `[
+			{
+			  "id": 45763,
+			  "name": "sha256:08a44bab0bddaddd8837a8b381aebc2e4b933768b981685a9e088360af0d3dd9",
+			  "url": "https://api.github.com/users/octocat/packages/container/hello_docker/versions/45763",
+			  "package_html_url": "https://github.com/users/octocat/packages/container/package/hello_docker",
+			  "created_at": `+referenceTimeStr+`,
+			  "updated_at": `+referenceTimeStr+`,
+			  "html_url": "https://github.com/users/octocat/packages/container/hello_docker/45763",
+			  "metadata": {
+				"package_type": "container",
+				"container": {
+				  "tags": [
+					"latest"
+				  ]
+				}
+			  }
+			}]`)
+	})
+
+	ctx := context.Background()
+	packages, _, err := client.Users.PackageGetAllVersions(ctx, "", "container", "hello_docker")
+	if err != nil {
+		t.Errorf("Users.Authenticated_PackageGetAllVersions returned error: %v", err)
+	}
+
+	want := []*PackageVersion{{
+		ID:             Int64(45763),
+		Name:           String("sha256:08a44bab0bddaddd8837a8b381aebc2e4b933768b981685a9e088360af0d3dd9"),
+		URL:            String("https://api.github.com/users/octocat/packages/container/hello_docker/versions/45763"),
+		PackageHTMLURL: String("https://github.com/users/octocat/packages/container/package/hello_docker"),
+		CreatedAt:      &Timestamp{referenceTime},
+		UpdatedAt:      &Timestamp{referenceTime},
+		HTMLURL:        String("https://github.com/users/octocat/packages/container/hello_docker/45763"),
+		Metadata: &PackageMetadata{
+			PackageType: String("container"),
+			Container: &PackageContainerMetadata{
+				Tags: []string{"latest"},
+			},
+		},
+	}}
+	if !cmp.Equal(packages, want) {
+		t.Errorf("Users.PackageGetAllVersions returned %+v, want %+v", packages, want)
+	}
+
+	const methodName = "PackageGetAllVersions"
+	testBadOptions(t, methodName, func() (err error) {
+		_, _, err = client.Users.PackageGetAllVersions(ctx, "\n", "", "")
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		got, resp, err := client.Users.PackageGetAllVersions(ctx, "", "", "")
+		if got != nil {
+			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+		}
+		return resp, err
+	})
+}
+
+func TestUsersService_specifiedUser_ListPackagesVersions(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/users/u/packages/container/hello_docker/versions", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "GET")
+		fmt.Fprint(w, `[
+			{
+			  "id": 45763,
+			  "name": "sha256:08a44bab0bddaddd8837a8b381aebc2e4b933768b981685a9e088360af0d3dd9",
+			  "url": "https://api.github.com/users/octocat/packages/container/hello_docker/versions/45763",
+			  "package_html_url": "https://github.com/users/octocat/packages/container/package/hello_docker",
+			  "created_at": `+referenceTimeStr+`,
+			  "updated_at": `+referenceTimeStr+`,
+			  "html_url": "https://github.com/users/octocat/packages/container/hello_docker/45763",
+			  "metadata": {
+				"package_type": "container",
+				"container": {
+				  "tags": [
+					"latest"
+				  ]
+				}
+			  }
+			}]`)
+	})
+
+	ctx := context.Background()
+	packages, _, err := client.Users.PackageGetAllVersions(ctx, "u", "container", "hello_docker")
+	if err != nil {
+		t.Errorf("Users.specifiedUser_PackageGetAllVersions returned error: %v", err)
+	}
+
+	want := []*PackageVersion{{
+		ID:             Int64(45763),
+		Name:           String("sha256:08a44bab0bddaddd8837a8b381aebc2e4b933768b981685a9e088360af0d3dd9"),
+		URL:            String("https://api.github.com/users/octocat/packages/container/hello_docker/versions/45763"),
+		PackageHTMLURL: String("https://github.com/users/octocat/packages/container/package/hello_docker"),
+		CreatedAt:      &Timestamp{referenceTime},
+		UpdatedAt:      &Timestamp{referenceTime},
+		HTMLURL:        String("https://github.com/users/octocat/packages/container/hello_docker/45763"),
+		Metadata: &PackageMetadata{
+			PackageType: String("container"),
+			Container: &PackageContainerMetadata{
+				Tags: []string{"latest"},
+			},
+		},
+	}}
+	if !cmp.Equal(packages, want) {
+		t.Errorf("Users.specifiedUser_PackageGetAllVersions returned %+v, want %+v", packages, want)
+	}
+
+	const methodName = "PackageGetAllVersions"
+	testBadOptions(t, methodName, func() (err error) {
+		_, _, err = client.Users.PackageGetAllVersions(ctx, "\n", "", "")
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		got, resp, err := client.Users.PackageGetAllVersions(ctx, "", "", "")
+		if got != nil {
+			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+		}
+		return resp, err
+	})
+}
+
+func TestUsersService_Authenticated_PackageGetVersion(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/user/packages/container/hello_docker/versions/45763", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "GET")
+		fmt.Fprint(w, `
+			{
+			  "id": 45763,
+			  "name": "sha256:08a44bab0bddaddd8837a8b381aebc2e4b933768b981685a9e088360af0d3dd9",
+			  "url": "https://api.github.com/users/octocat/packages/container/hello_docker/versions/45763",
+			  "package_html_url": "https://github.com/users/octocat/packages/container/package/hello_docker",
+			  "created_at": `+referenceTimeStr+`,
+			  "updated_at": `+referenceTimeStr+`,
+			  "html_url": "https://github.com/users/octocat/packages/container/hello_docker/45763",
+			  "metadata": {
+				"package_type": "container",
+				"container": {
+				  "tags": [
+					"latest"
+				  ]
+				}
+			  }
+			}`)
+	})
+
+	ctx := context.Background()
+	packages, _, err := client.Users.PackageGetVersion(ctx, "", "container", "hello_docker", 45763)
+	if err != nil {
+		t.Errorf("Users.PackageGetVersion returned error: %v", err)
+	}
+
+	want := &PackageVersion{
+		ID:             Int64(45763),
+		Name:           String("sha256:08a44bab0bddaddd8837a8b381aebc2e4b933768b981685a9e088360af0d3dd9"),
+		URL:            String("https://api.github.com/users/octocat/packages/container/hello_docker/versions/45763"),
+		PackageHTMLURL: String("https://github.com/users/octocat/packages/container/package/hello_docker"),
+		CreatedAt:      &Timestamp{referenceTime},
+		UpdatedAt:      &Timestamp{referenceTime},
+		HTMLURL:        String("https://github.com/users/octocat/packages/container/hello_docker/45763"),
+		Metadata: &PackageMetadata{
+			PackageType: String("container"),
+			Container: &PackageContainerMetadata{
+				Tags: []string{"latest"},
+			},
+		},
+	}
+	if !cmp.Equal(packages, want) {
+		t.Errorf("Users.Authenticated_PackageGetVersion returned %+v, want %+v", packages, want)
+	}
+
+	const methodName = "PackageGetVersion"
+	testBadOptions(t, methodName, func() (err error) {
+		_, _, err = client.Users.PackageGetVersion(ctx, "\n", "", "", 0)
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		got, resp, err := client.Users.PackageGetVersion(ctx, "", "", "", 45763)
+		if got != nil {
+			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+		}
+		return resp, err
+	})
+}
+
+func TestUsersService_specifiedUser_PackageGetVersion(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/users/u/packages/container/hello_docker/versions/45763", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "GET")
+		fmt.Fprint(w, `
+			{
+			  "id": 45763,
+			  "name": "sha256:08a44bab0bddaddd8837a8b381aebc2e4b933768b981685a9e088360af0d3dd9",
+			  "url": "https://api.github.com/users/octocat/packages/container/hello_docker/versions/45763",
+			  "package_html_url": "https://github.com/users/octocat/packages/container/package/hello_docker",
+			  "created_at": `+referenceTimeStr+`,
+			  "updated_at": `+referenceTimeStr+`,
+			  "html_url": "https://github.com/users/octocat/packages/container/hello_docker/45763",
+			  "metadata": {
+				"package_type": "container",
+				"container": {
+				  "tags": [
+					"latest"
+				  ]
+				}
+			  }
+			}`)
+	})
+
+	ctx := context.Background()
+	packages, _, err := client.Users.PackageGetVersion(ctx, "u", "container", "hello_docker", 45763)
+	if err != nil {
+		t.Errorf("Users.specifiedUser_PackageGetVersion returned error: %v", err)
+	}
+
+	want := &PackageVersion{
+		ID:             Int64(45763),
+		Name:           String("sha256:08a44bab0bddaddd8837a8b381aebc2e4b933768b981685a9e088360af0d3dd9"),
+		URL:            String("https://api.github.com/users/octocat/packages/container/hello_docker/versions/45763"),
+		PackageHTMLURL: String("https://github.com/users/octocat/packages/container/package/hello_docker"),
+		CreatedAt:      &Timestamp{referenceTime},
+		UpdatedAt:      &Timestamp{referenceTime},
+		HTMLURL:        String("https://github.com/users/octocat/packages/container/hello_docker/45763"),
+		Metadata: &PackageMetadata{
+			PackageType: String("container"),
+			Container: &PackageContainerMetadata{
+				Tags: []string{"latest"},
+			},
+		},
+	}
+	if !cmp.Equal(packages, want) {
+		t.Errorf("Users.specifiedUser_PackageGetVersion returned %+v, want %+v", packages, want)
+	}
+
+	const methodName = "PackageGetVersion"
+	testBadOptions(t, methodName, func() (err error) {
+		_, _, err = client.Users.PackageGetVersion(ctx, "\n", "", "", 0)
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		got, resp, err := client.Users.PackageGetVersion(ctx, "", "", "", 45763)
+		if got != nil {
+			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+		}
+		return resp, err
+	})
+}
+
+func TestUsersService_Authenticated_PackageDeleteVersion(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/user/packages/container/hello_docker/versions/45763", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "DELETE")
+	})
+
+	ctx := context.Background()
+	_, err := client.Users.PackageDeleteVersion(ctx, "", "container", "hello_docker", 45763)
+	if err != nil {
+		t.Errorf("Users.Authenticated_PackageDeleteVersion returned error: %v", err)
+	}
+
+	const methodName = "PackageDeleteVersion"
+	testBadOptions(t, methodName, func() (err error) {
+		_, err = client.Users.PackageDeleteVersion(ctx, "\n", "", "", 0)
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		return client.Users.PackageDeleteVersion(ctx, "", "", "", 45763)
+	})
+}
+
+func TestUsersService_specifiedUser_PackageDeleteVersion(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/users/u/packages/container/hello_docker/versions/45763", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "DELETE")
+	})
+
+	ctx := context.Background()
+	_, err := client.Users.PackageDeleteVersion(ctx, "u", "container", "hello_docker", 45763)
+	if err != nil {
+		t.Errorf("Users.specifiedUser_PackageDeleteVersion returned error: %v", err)
+	}
+
+	const methodName = "PackageDeleteVersion"
+	testBadOptions(t, methodName, func() (err error) {
+		_, err = client.Users.PackageDeleteVersion(ctx, "\n", "", "", 0)
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		return client.Users.PackageDeleteVersion(ctx, "", "", "", 45763)
+	})
+}
+
+func TestUsersService_Authenticated_PackageRestoreVersion(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/user/packages/container/hello_docker/versions/45763/restore", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "POST")
+	})
+
+	ctx := context.Background()
+	_, err := client.Users.PackageRestoreVersion(ctx, "", "container", "hello_docker", 45763)
+	if err != nil {
+		t.Errorf("Users.Authenticated_PackageRestoreVersion returned error: %v", err)
+	}
+
+	const methodName = "PackageRestoreVersion"
+	testBadOptions(t, methodName, func() (err error) {
+		_, err = client.Users.PackageRestoreVersion(ctx, "\n", "", "", 0)
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		return client.Users.PackageRestoreVersion(ctx, "", "", "", 45763)
+	})
+}
+
+func TestUsersService_specifiedUser_PackageRestoreVersion(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/users/u/packages/container/hello_docker/versions/45763/restore", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "POST")
+	})
+
+	ctx := context.Background()
+	_, err := client.Users.PackageRestoreVersion(ctx, "u", "container", "hello_docker", 45763)
+	if err != nil {
+		t.Errorf("Users.specifiedUser_PackageRestoreVersion returned error: %v", err)
+	}
+
+	const methodName = "PackageRestoreVersion"
+	testBadOptions(t, methodName, func() (err error) {
+		_, err = client.Users.PackageRestoreVersion(ctx, "\n", "", "", 0)
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		return client.Users.PackageRestoreVersion(ctx, "", "", "", 45763)
+	})
+}
diff --git a/scrape/apps_test.go b/scrape/apps_test.go
index ce9c04d6..7987c8f5 100644
--- a/scrape/apps_test.go
+++ b/scrape/apps_test.go
@@ -43,7 +43,6 @@ func Test_AppRestrictionsEnabled(t *testing.T) {
 			if want := tt.want; got != want {
 				t.Errorf("AppRestrictionsEnabled returned %t, want %t", got, want)
 			}
-
 		})
 	}
 }
@@ -83,7 +82,6 @@ func Test_ListOAuthApps(t *testing.T) {
 	if !cmp.Equal(got, want) {
 		t.Errorf("ListOAuthApps(o) returned %v, want %v", got, want)
 	}
-
 }
 
 func Test_CreateApp(t *testing.T) {
diff --git a/update-urls/main_test.go b/update-urls/main_test.go
index e9c5ef3d..49f165fd 100644
--- a/update-urls/main_test.go
+++ b/update-urls/main_test.go
@@ -233,7 +233,7 @@ type fakeDocCache struct {
 	endpoints endpointsByFragmentID
 }
 
-func (f *fakeDocCache) UrlByMethodAndPath(methodAndPath string) (string, bool) {
+func (f *fakeDocCache) URLByMethodAndPath(methodAndPath string) (string, bool) {
 	f.t.Helper()
 	for fragmentID, endpoints := range f.endpoints {
 		for _, endpoint := range endpoints {
@@ -241,13 +241,13 @@ func (f *fakeDocCache) UrlByMethodAndPath(methodAndPath string) (string, bool) {
 				key := fmt.Sprintf("%v %v", endpoint.httpMethod, urlFormat)
 				if key == methodAndPath {
 					url := fmt.Sprintf("%v#%v", f.baseURL, fragmentID)
-					// log.Printf("UrlByMethodAndPath(%q) = (%q, true)", methodAndPath, url)
+					// log.Printf("URLByMethodAndPath(%q) = (%q, true)", methodAndPath, url)
 					return url, true
 				}
 			}
 		}
 	}
-	f.t.Fatalf("fakeDocCache.UrlByMethodAndPath: unable to find method %v", methodAndPath)
+	f.t.Fatalf("fakeDocCache.URLByMethodAndPath: unable to find method %v", methodAndPath)
 	return "", false
 }