Repository: google/go-github
Pull request #2079 (2021-09-03 05:59:16)

Add test cases for JSON resources marshaling
1. repo_hooks.go

codecov[bot]: # [Codecov](https://codecov.io/gh/google/go-github/pull/2079?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google) Report
> Merging [#2079](https://codecov.io/gh/google/go-github/pull/2079?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google) (89ce35a) into [master](https://codecov.io/gh/google/go-github/commit/5dfec5a1706ea582ed74f60c100893c9cc9b0b3e?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google) (5dfec5a) will **increase** coverage by `0.00%`.
> The diff coverage is `n/a`.

[![Impacted file tree graph](https://codecov.io/gh/google/go-github/pull/2079/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/2079?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google)

```diff
@@           Coverage Diff           @@
##           master    #2079   +/-   ##
=======================================
  Coverage   97.75%   97.75%           
=======================================
  Files         107      107           
  Lines        9600     9601    +1     
=======================================
+ Hits         9384     9385    +1     
  Misses        150      150           
  Partials       66       66           
```


| [Impacted Files](https://codecov.io/gh/google/go-github/pull/2079?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google) | Coverage Δ | |
|---|---|---|
| [github/repos.go](https://codecov.io/gh/google/go-github/pull/2079/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google#diff-Z2l0aHViL3JlcG9zLmdv) | `98.64% <0.00%> (+<0.01%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/google/go-github/pull/2079?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/2079?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google). Last update [5dfec5a...89ce35a](https://codecov.io/gh/google/go-github/pull/2079?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/.gitignore b/.gitignore
index 3d439783..aea73858 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,4 +4,5 @@ coverage.out
 # intellij files
 .idea/
 vendor/
-.DS_Store
\ No newline at end of file
+.DS_Store
+.vscode
\ No newline at end of file
diff --git a/github/actions_workflow_runs.go b/github/actions_workflow_runs.go
index 64274a3d..b2c40d47 100644
--- a/github/actions_workflow_runs.go
+++ b/github/actions_workflow_runs.go
@@ -49,10 +49,11 @@ type WorkflowRuns struct {
 
 // ListWorkflowRunsOptions specifies optional parameters to ListWorkflowRuns.
 type ListWorkflowRunsOptions struct {
-	Actor  string `url:"actor,omitempty"`
-	Branch string `url:"branch,omitempty"`
-	Event  string `url:"event,omitempty"`
-	Status string `url:"status,omitempty"`
+	Actor   string `url:"actor,omitempty"`
+	Branch  string `url:"branch,omitempty"`
+	Event   string `url:"event,omitempty"`
+	Status  string `url:"status,omitempty"`
+	Created string `url:"created,omitempty"`
 	ListOptions
 }
 
diff --git a/github/event.go b/github/event.go
index 4b87142a..8f1a0f2e 100644
--- a/github/event.go
+++ b/github/event.go
@@ -124,6 +124,8 @@ func (e *Event) ParsePayload() (payload interface{}, err error) {
 		payload = &WatchEvent{}
 	case "WorkflowDispatchEvent":
 		payload = &WorkflowDispatchEvent{}
+	case "WorkflowJobEvent":
+		payload = &WorkflowJobEvent{}
 	case "WorkflowRunEvent":
 		payload = &WorkflowRunEvent{}
 	}
diff --git a/github/event_types.go b/github/event_types.go
index f99a1296..384aa3a1 100644
--- a/github/event_types.go
+++ b/github/event_types.go
@@ -1083,6 +1083,20 @@ type WorkflowDispatchEvent struct {
 	Sender *User         `json:"sender,omitempty"`
 }
 
+// WorkflowJobEvent is triggered when a job is queued, started or completed.
+//
+// GitHub API docs: pending
+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"`
+}
+
 // WorkflowRunEvent is triggered when a GitHub Actions workflow run is requested or completed.
 //
 // GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#workflow_run
diff --git a/github/github-accessors.go b/github/github-accessors.go
index 790d185b..8422d6a7 100644
--- a/github/github-accessors.go
+++ b/github/github-accessors.go
@@ -1188,6 +1188,46 @@ func (a *AuthorizationUpdateRequest) GetNoteURL() string {
 	return *a.NoteURL
 }
 
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (a *Autolink) GetID() int64 {
+	if a == nil || a.ID == nil {
+		return 0
+	}
+	return *a.ID
+}
+
+// GetKeyPrefix returns the KeyPrefix field if it's non-nil, zero value otherwise.
+func (a *Autolink) GetKeyPrefix() string {
+	if a == nil || a.KeyPrefix == nil {
+		return ""
+	}
+	return *a.KeyPrefix
+}
+
+// GetURLTemplate returns the URLTemplate field if it's non-nil, zero value otherwise.
+func (a *Autolink) GetURLTemplate() string {
+	if a == nil || a.URLTemplate == nil {
+		return ""
+	}
+	return *a.URLTemplate
+}
+
+// GetKeyPrefix returns the KeyPrefix field if it's non-nil, zero value otherwise.
+func (a *AutolinkOptions) GetKeyPrefix() string {
+	if a == nil || a.KeyPrefix == nil {
+		return ""
+	}
+	return *a.KeyPrefix
+}
+
+// GetURLTemplate returns the URLTemplate field if it's non-nil, zero value otherwise.
+func (a *AutolinkOptions) GetURLTemplate() string {
+	if a == nil || a.URLTemplate == nil {
+		return ""
+	}
+	return *a.URLTemplate
+}
+
 // GetAppID returns the AppID field if it's non-nil, zero value otherwise.
 func (a *AutoTriggerCheck) GetAppID() int64 {
 	if a == nil || a.AppID == nil {
@@ -2508,6 +2548,14 @@ func (c *CommunityHealthFiles) GetCodeOfConduct() *Metric {
 	return c.CodeOfConduct
 }
 
+// GetCodeOfConductFile returns the CodeOfConductFile field.
+func (c *CommunityHealthFiles) GetCodeOfConductFile() *Metric {
+	if c == nil {
+		return nil
+	}
+	return c.CodeOfConductFile
+}
+
 // GetContributing returns the Contributing field.
 func (c *CommunityHealthFiles) GetContributing() *Metric {
 	if c == nil {
@@ -2548,6 +2596,30 @@ func (c *CommunityHealthFiles) GetReadme() *Metric {
 	return c.Readme
 }
 
+// GetContentReportsEnabled returns the ContentReportsEnabled field if it's non-nil, zero value otherwise.
+func (c *CommunityHealthMetrics) GetContentReportsEnabled() bool {
+	if c == nil || c.ContentReportsEnabled == nil {
+		return false
+	}
+	return *c.ContentReportsEnabled
+}
+
+// GetDescription returns the Description field if it's non-nil, zero value otherwise.
+func (c *CommunityHealthMetrics) GetDescription() string {
+	if c == nil || c.Description == nil {
+		return ""
+	}
+	return *c.Description
+}
+
+// GetDocumentation returns the Documentation field if it's non-nil, zero value otherwise.
+func (c *CommunityHealthMetrics) GetDocumentation() string {
+	if c == nil || c.Documentation == nil {
+		return ""
+	}
+	return *c.Documentation
+}
+
 // GetFiles returns the Files field.
 func (c *CommunityHealthMetrics) GetFiles() *CommunityHealthFiles {
 	if c == nil {
@@ -7180,6 +7252,30 @@ func (l *ListRepositories) GetTotalCount() int {
 	return *l.TotalCount
 }
 
+// GetCount returns the Count field if it's non-nil, zero value otherwise.
+func (l *ListSCIMProvisionedIdentitiesOptions) GetCount() int {
+	if l == nil || l.Count == nil {
+		return 0
+	}
+	return *l.Count
+}
+
+// GetFilter returns the Filter field if it's non-nil, zero value otherwise.
+func (l *ListSCIMProvisionedIdentitiesOptions) GetFilter() string {
+	if l == nil || l.Filter == nil {
+		return ""
+	}
+	return *l.Filter
+}
+
+// GetStartIndex returns the StartIndex field if it's non-nil, zero value otherwise.
+func (l *ListSCIMProvisionedIdentitiesOptions) GetStartIndex() int {
+	if l == nil || l.StartIndex == nil {
+		return 0
+	}
+	return *l.StartIndex
+}
+
 // GetEndColumn returns the EndColumn field if it's non-nil, zero value otherwise.
 func (l *Location) GetEndColumn() int {
 	if l == nil || l.EndColumn == nil {
@@ -7724,6 +7820,22 @@ func (m *Metric) GetName() string {
 	return *m.Name
 }
 
+// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise.
+func (m *Metric) GetNodeID() string {
+	if m == nil || m.NodeID == nil {
+		return ""
+	}
+	return *m.NodeID
+}
+
+// GetSPDXID returns the SPDXID field if it's non-nil, zero value otherwise.
+func (m *Metric) GetSPDXID() string {
+	if m == nil || m.SPDXID == nil {
+		return ""
+	}
+	return *m.SPDXID
+}
+
 // GetURL returns the URL field if it's non-nil, zero value otherwise.
 func (m *Metric) GetURL() string {
 	if m == nil || m.URL == nil {
@@ -14580,6 +14692,54 @@ func (r *RunnerLabels) GetType() string {
 	return *r.Type
 }
 
+// GetActive returns the Active field if it's non-nil, zero value otherwise.
+func (s *SCIMUserAttributes) GetActive() bool {
+	if s == nil || s.Active == nil {
+		return false
+	}
+	return *s.Active
+}
+
+// GetDisplayName returns the DisplayName field if it's non-nil, zero value otherwise.
+func (s *SCIMUserAttributes) GetDisplayName() string {
+	if s == nil || s.DisplayName == nil {
+		return ""
+	}
+	return *s.DisplayName
+}
+
+// GetExternalID returns the ExternalID field if it's non-nil, zero value otherwise.
+func (s *SCIMUserAttributes) GetExternalID() string {
+	if s == nil || s.ExternalID == nil {
+		return ""
+	}
+	return *s.ExternalID
+}
+
+// GetPrimary returns the Primary field if it's non-nil, zero value otherwise.
+func (s *SCIMUserEmail) GetPrimary() bool {
+	if s == nil || s.Primary == nil {
+		return false
+	}
+	return *s.Primary
+}
+
+// GetType returns the Type field if it's non-nil, zero value otherwise.
+func (s *SCIMUserEmail) GetType() string {
+	if s == nil || s.Type == nil {
+		return ""
+	}
+	return *s.Type
+}
+
+// GetFormatted returns the Formatted field if it's non-nil, zero value otherwise.
+func (s *SCIMUserName) GetFormatted() string {
+	if s == nil || s.Formatted == nil {
+		return ""
+	}
+	return *s.Formatted
+}
+
 // GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise.
 func (s *SelectedReposList) GetTotalCount() int {
 	if s == nil || s.TotalCount == nil {
@@ -16124,6 +16284,14 @@ func (t *TreeEntry) GetURL() string {
 	return *t.URL
 }
 
+// GetPath returns the Path field if it's non-nil, zero value otherwise.
+func (u *UpdateAttributeForSCIMUserOperations) GetPath() string {
+	if u == nil || u.Path == nil {
+		return ""
+	}
+	return *u.Path
+}
+
 // GetCompletedAt returns the CompletedAt field if it's non-nil, zero value otherwise.
 func (u *UpdateCheckRunOptions) GetCompletedAt() Timestamp {
 	if u == nil || u.CompletedAt == nil {
@@ -17468,6 +17636,46 @@ func (w *WorkflowJob) GetURL() string {
 	return *w.URL
 }
 
+// GetAction returns the Action field if it's non-nil, zero value otherwise.
+func (w *WorkflowJobEvent) GetAction() string {
+	if w == nil || w.Action == nil {
+		return ""
+	}
+	return *w.Action
+}
+
+// GetOrg returns the Org field.
+func (w *WorkflowJobEvent) GetOrg() *Organization {
+	if w == nil {
+		return nil
+	}
+	return w.Org
+}
+
+// GetRepo returns the Repo field.
+func (w *WorkflowJobEvent) GetRepo() *Repository {
+	if w == nil {
+		return nil
+	}
+	return w.Repo
+}
+
+// GetSender returns the Sender field.
+func (w *WorkflowJobEvent) GetSender() *User {
+	if w == nil {
+		return nil
+	}
+	return w.Sender
+}
+
+// GetWorkflowJob returns the WorkflowJob field.
+func (w *WorkflowJobEvent) GetWorkflowJob() *WorkflowJob {
+	if w == nil {
+		return nil
+	}
+	return w.WorkflowJob
+}
+
 // GetArtifactsURL returns the ArtifactsURL field if it's non-nil, zero value otherwise.
 func (w *WorkflowRun) GetArtifactsURL() string {
 	if w == nil || w.ArtifactsURL == nil {
diff --git a/github/github.go b/github/github.go
index 56b63d17..a2727ccf 100644
--- a/github/github.go
+++ b/github/github.go
@@ -76,9 +76,6 @@ const (
 	// https://developer.github.com/changes/2017-02-28-user-blocking-apis-and-webhook/
 	mediaTypeBlockUsersPreview = "application/vnd.github.giant-sentry-fist-preview+json"
 
-	// https://developer.github.com/changes/2017-02-09-community-health/
-	mediaTypeRepositoryCommunityHealthMetricsPreview = "application/vnd.github.black-panther-preview+json"
-
 	// https://developer.github.com/changes/2017-05-23-coc-api/
 	mediaTypeCodesOfConductPreview = "application/vnd.github.scarlet-witch-preview+json"
 
@@ -181,6 +178,7 @@ type Client struct {
 	PullRequests   *PullRequestsService
 	Reactions      *ReactionsService
 	Repositories   *RepositoriesService
+	SCIM           *SCIMService
 	Search         *SearchService
 	Teams          *TeamsService
 	Users          *UsersService
@@ -308,6 +306,7 @@ func NewClient(httpClient *http.Client) *Client {
 	c.PullRequests = (*PullRequestsService)(&c.common)
 	c.Reactions = (*ReactionsService)(&c.common)
 	c.Repositories = (*RepositoriesService)(&c.common)
+	c.SCIM = (*SCIMService)(&c.common)
 	c.Search = (*SearchService)(&c.common)
 	c.Teams = (*TeamsService)(&c.common)
 	c.Users = (*UsersService)(&c.common)
diff --git a/github/messages.go b/github/messages.go
index caa596a2..e46435c9 100644
--- a/github/messages.go
+++ b/github/messages.go
@@ -92,6 +92,7 @@ var (
 		"user":                           "UserEvent",
 		"watch":                          "WatchEvent",
 		"workflow_dispatch":              "WorkflowDispatchEvent",
+		"workflow_job":                   "WorkflowJobEvent",
 		"workflow_run":                   "WorkflowRunEvent",
 	}
 )
diff --git a/github/orgs_hooks_deliveries.go b/github/orgs_hooks_deliveries.go
index 6ab2d7aa..d1fb5c83 100644
--- a/github/orgs_hooks_deliveries.go
+++ b/github/orgs_hooks_deliveries.go
@@ -52,3 +52,22 @@ func (s *OrganizationsService) GetHookDelivery(ctx context.Context, owner string
 
 	return h, resp, nil
 }
+
+// RedeliverHookDelivery redelivers a delivery for a webhook configured in an organization.
+//
+// GitHub API docs: https://docs.github.com/en/rest/reference/orgs#redeliver-a-delivery-for-an-organization-webhook
+func (s *OrganizationsService) RedeliverHookDelivery(ctx context.Context, owner string, hookID, deliveryID int64) (*HookDelivery, *Response, error) {
+	u := fmt.Sprintf("orgs/%v/hooks/%v/deliveries/%v/attempts", owner, hookID, deliveryID)
+	req, err := s.client.NewRequest("POST", u, nil)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	h := new(HookDelivery)
+	resp, err := s.client.Do(ctx, req, h)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return h, resp, nil
+}
diff --git a/github/repos_autolinks.go b/github/repos_autolinks.go
new file mode 100644
index 00000000..b6404783
--- /dev/null
+++ b/github/repos_autolinks.go
@@ -0,0 +1,102 @@
+// 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"
+)
+
+// AutolinkOptions specifies parameters for RepositoriesService.AddAutolink method.
+type AutolinkOptions struct {
+	KeyPrefix   *string `json:"key_prefix,omitempty"`
+	URLTemplate *string `json:"url_template,omitempty"`
+}
+
+// Autolink represents autolinks to external resources like JIRA issues and Zendesk tickets.
+type Autolink struct {
+	ID          *int64  `json:"id,omitempty"`
+	KeyPrefix   *string `json:"key_prefix,omitempty"`
+	URLTemplate *string `json:"url_template,omitempty"`
+}
+
+// ListAutolinks returns a list of autolinks configured for the given repository.
+// Information about autolinks are only available to repository administrators.
+//
+// GitHub API docs: https://docs.github.com/en/rest/reference/repos#list-all-autolinks-of-a-repository
+func (s *RepositoriesService) ListAutolinks(ctx context.Context, owner, repo string, opts *ListOptions) ([]*Autolink, *Response, error) {
+	u := fmt.Sprintf("repos/%v/%v/autolinks", owner, repo)
+	u, err := addOptions(u, opts)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	req, err := s.client.NewRequest("GET", u, nil)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	var autolinks []*Autolink
+	resp, err := s.client.Do(ctx, req, &autolinks)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return autolinks, resp, nil
+}
+
+// AddAutolink creates an autolink reference for a repository.
+// Users with admin access to the repository can create an autolink.
+//
+// GitHub API docs: https://docs.github.com/en/rest/reference/repos#create-an-autolink-reference-for-a-repository
+func (s *RepositoriesService) AddAutolink(ctx context.Context, owner, repo string, opts *AutolinkOptions) (*Autolink, *Response, error) {
+	u := fmt.Sprintf("repos/%v/%v/autolinks", owner, repo)
+	req, err := s.client.NewRequest("POST", u, opts)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	al := new(Autolink)
+	resp, err := s.client.Do(ctx, req, al)
+	if err != nil {
+		return nil, resp, err
+	}
+	return al, resp, nil
+}
+
+// GetAutolink returns a single autolink reference by ID that was configured for the given repository.
+// Information about autolinks are only available to repository administrators.
+//
+// GitHub API docs: https://docs.github.com/en/rest/reference/repos#get-an-autolink-reference-of-a-repository
+func (s *RepositoriesService) GetAutolink(ctx context.Context, owner, repo string, id int64) (*Autolink, *Response, error) {
+	u := fmt.Sprintf("repos/%v/%v/autolinks/%v", owner, repo, id)
+
+	req, err := s.client.NewRequest("GET", u, nil)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	var autolink *Autolink
+	resp, err := s.client.Do(ctx, req, &autolink)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return autolink, resp, nil
+}
+
+// DeleteAutolink deletes a single autolink reference by ID that was configured for the given repository.
+// Information about autolinks are only available to repository administrators.
+//
+// GitHub API docs: https://docs.github.com/en/rest/reference/repos#delete-an-autolink-reference-from-a-repository
+func (s *RepositoriesService) DeleteAutolink(ctx context.Context, owner, repo string, id int64) (*Response, error) {
+	u := fmt.Sprintf("repos/%v/%v/autolinks/%v", owner, repo, id)
+	req, err := s.client.NewRequest("DELETE", u, nil)
+	if err != nil {
+		return nil, err
+	}
+	return s.client.Do(ctx, req, nil)
+}
diff --git a/github/repos_community_health.go b/github/repos_community_health.go
index aeb4277a..92e4d082 100644
--- a/github/repos_community_health.go
+++ b/github/repos_community_health.go
@@ -15,13 +15,16 @@ import (
 type Metric struct {
 	Name    *string `json:"name"`
 	Key     *string `json:"key"`
+	SPDXID  *string `json:"spdx_id"`
 	URL     *string `json:"url"`
 	HTMLURL *string `json:"html_url"`
+	NodeID  *string `json:"node_id"`
 }
 
 // CommunityHealthFiles represents the different files in the community health metrics response.
 type CommunityHealthFiles struct {
 	CodeOfConduct       *Metric `json:"code_of_conduct"`
+	CodeOfConductFile   *Metric `json:"code_of_conduct_file"`
 	Contributing        *Metric `json:"contributing"`
 	IssueTemplate       *Metric `json:"issue_template"`
 	PullRequestTemplate *Metric `json:"pull_request_template"`
@@ -31,14 +34,17 @@ type CommunityHealthFiles struct {
 
 // CommunityHealthMetrics represents a response containing the community metrics of a repository.
 type CommunityHealthMetrics struct {
-	HealthPercentage *int                  `json:"health_percentage"`
-	Files            *CommunityHealthFiles `json:"files"`
-	UpdatedAt        *time.Time            `json:"updated_at"`
+	HealthPercentage      *int                  `json:"health_percentage"`
+	Description           *string               `json:"description"`
+	Documentation         *string               `json:"documentation"`
+	Files                 *CommunityHealthFiles `json:"files"`
+	UpdatedAt             *time.Time            `json:"updated_at"`
+	ContentReportsEnabled *bool                 `json:"content_reports_enabled"`
 }
 
 // GetCommunityHealthMetrics retrieves all the community health  metrics for a  repository.
 //
-// GitHub API docs: https://docs.github.com/en/free-pro-team@latest/rest/reference/repos/#get-community-profile-metrics
+// GitHub API docs: https://docs.github.com/en/rest/reference/repos#get-community-profile-metrics
 func (s *RepositoriesService) GetCommunityHealthMetrics(ctx context.Context, owner, repo string) (*CommunityHealthMetrics, *Response, error) {
 	u := fmt.Sprintf("repos/%v/%v/community/profile", owner, repo)
 	req, err := s.client.NewRequest("GET", u, nil)
@@ -46,9 +52,6 @@ func (s *RepositoriesService) GetCommunityHealthMetrics(ctx context.Context, own
 		return nil, nil, err
 	}
 
-	// TODO: remove custom Accept header when this API fully launches.
-	req.Header.Set("Accept", mediaTypeRepositoryCommunityHealthMetricsPreview)
-
 	metrics := &CommunityHealthMetrics{}
 	resp, err := s.client.Do(ctx, req, metrics)
 	if err != nil {
diff --git a/github/scim.go b/github/scim.go
new file mode 100644
index 00000000..7a12d85b
--- /dev/null
+++ b/github/scim.go
@@ -0,0 +1,163 @@
+// 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"
+	"encoding/json"
+	"fmt"
+)
+
+// SCIMService provides access to SCIM related functions in the
+// GitHub API.
+//
+// GitHub API docs: https://docs.github.com/en/rest/reference/scim
+type SCIMService service
+
+// SCIMUserAttributes represents supported SCIM User attributes.
+//
+// GitHub API docs: https://docs.github.com/en/rest/reference/scim#supported-scim-user-attributes
+type SCIMUserAttributes struct {
+	UserName    string           `json:"userName"`              // Configured by the admin. Could be an email, login, or username. (Required.)
+	Name        SCIMUserName     `json:"name"`                  // (Required.)
+	DisplayName *string          `json:"displayName,omitempty"` // The name of the user, suitable for display to end-users. (Optional.)
+	Emails      []*SCIMUserEmail `json:"emails"`                // User emails. (Required.)
+	Schemas     []string         `json:"schemas,omitempty"`     // (Optional.)
+	ExternalID  *string          `json:"externalId,omitempty"`  // (Optional.)
+	Groups      []string         `json:"groups,omitempty"`      // (Optional.)
+	Active      *bool            `json:"active,omitempty"`      // (Optional.)
+}
+
+// SCIMUserName represents SCIM user information.
+type SCIMUserName struct {
+	GivenName  string  `json:"givenName"`           // The first name of the user. (Required.)
+	FamilyName string  `json:"familyName"`          // The family name of the user. (Required.)
+	Formatted  *string `json:"formatted,omitempty"` // (Optional.)
+}
+
+//SCIMUserEmail represents SCIM user email.
+type SCIMUserEmail struct {
+	Value   string  `json:"value"`             // (Required.)
+	Primary *bool   `json:"primary,omitempty"` // (Optional.)
+	Type    *string `json:"type,omitempty"`    // (Optional.)
+}
+
+// ListSCIMProvisionedIdentitiesOptions represents options for ListSCIMProvisionedIdentities.
+//
+// Github API docs: https://docs.github.com/en/rest/reference/scim#list-scim-provisioned-identities--parameters
+type ListSCIMProvisionedIdentitiesOptions struct {
+	StartIndex *int `json:"startIndex,omitempty"` // Used for pagination: the index of the first result to return. (Optional.)
+	Count      *int `json:"count,omitempty"`      // Used for pagination: the number of results to return. (Optional.)
+	// Filter results using the equals query parameter operator (eq).
+	// You can filter results that are equal to id, userName, emails, and external_id.
+	// For example, to search for an identity with the userName Octocat, you would use this query: ?filter=userName%20eq%20\"Octocat\".
+	// To filter results for the identity with the email octocat@github.com, you would use this query: ?filter=emails%20eq%20\"octocat@github.com\".
+	// (Optional.)
+	Filter *string `json:"filter,omitempty"`
+}
+
+// ListSCIMProvisionedIdentities lists SCIM provisioned identities.
+//
+// GitHub API docs: https://docs.github.com/en/rest/reference/scim#list-scim-provisioned-identities
+func (s *SCIMService) ListSCIMProvisionedIdentities(ctx context.Context, org string, opts *ListSCIMProvisionedIdentitiesOptions) (*Response, error) {
+	u := fmt.Sprintf("scim/v2/organizations/%v/Users", org)
+	u, err := addOptions(u, opts)
+	if err != nil {
+		return nil, err
+	}
+	req, err := s.client.NewRequest("GET", u, nil)
+	if err != nil {
+		return nil, err
+	}
+	return s.client.Do(ctx, req, nil)
+}
+
+// ProvisionAndInviteSCIMUser provisions organization membership for a user, and sends an activation email to the email address.
+//
+// GitHub API docs: https://docs.github.com/en/rest/reference/scim#provision-and-invite-a-scim-user
+func (s *SCIMService) ProvisionAndInviteSCIMUser(ctx context.Context, org string, opts *SCIMUserAttributes) (*Response, error) {
+	u := fmt.Sprintf("scim/v2/organizations/%v/Users", org)
+	u, err := addOptions(u, opts)
+	if err != nil {
+		return nil, err
+	}
+	req, err := s.client.NewRequest("POST", u, nil)
+	if err != nil {
+		return nil, err
+	}
+	return s.client.Do(ctx, req, nil)
+}
+
+// GetSCIMProvisioningInfoForUser returns SCIM provisioning information for a user.
+//
+// GitHub API docs: https://docs.github.com/en/rest/reference/scim#get-scim-provisioning-information-for-a-user
+func (s *SCIMService) GetSCIMProvisioningInfoForUser(ctx context.Context, org, scimUserID string) (*Response, error) {
+	u := fmt.Sprintf("scim/v2/organizations/%v/Users/%v", org, scimUserID)
+	req, err := s.client.NewRequest("GET", u, nil)
+	if err != nil {
+		return nil, err
+	}
+	return s.client.Do(ctx, req, nil)
+}
+
+// UpdateProvisionedOrgMembership updates a provisioned organization membership.
+//
+// GitHub API docs: https://docs.github.com/en/rest/reference/scim#update-a-provisioned-organization-membership
+func (s *SCIMService) UpdateProvisionedOrgMembership(ctx context.Context, org, scimUserID string, opts *SCIMUserAttributes) (*Response, error) {
+	u := fmt.Sprintf("scim/v2/organizations/%v/Users/%v", org, scimUserID)
+	u, err := addOptions(u, opts)
+	if err != nil {
+		return nil, err
+	}
+	req, err := s.client.NewRequest("PUT", u, nil)
+	if err != nil {
+		return nil, err
+	}
+	return s.client.Do(ctx, req, nil)
+}
+
+// UpdateAttributeForSCIMUserOptions represents options for UpdateAttributeForSCIMUser.
+//
+// GitHub API docs: https://docs.github.com/en/rest/reference/scim#update-an-attribute-for-a-scim-user--parameters
+type UpdateAttributeForSCIMUserOptions struct {
+	Schemas    []string                             `json:"schemas,omitempty"` // (Optional.)
+	Operations UpdateAttributeForSCIMUserOperations `json:"operations"`        // Set of operations to be performed. (Required.)
+}
+
+// UpdateAttributeForSCIMUserOperations represents operations for UpdateAttributeForSCIMUser.
+type UpdateAttributeForSCIMUserOperations struct {
+	Op    string          `json:"op"`              // (Required.)
+	Path  *string         `json:"path,omitempty"`  // (Optional.)
+	Value json.RawMessage `json:"value,omitempty"` // (Optional.)
+}
+
+// UpdateAttributeForSCIMUser updates an attribute for an SCIM user.
+//
+// GitHub API docs: https://docs.github.com/en/rest/reference/scim#update-an-attribute-for-a-scim-user
+func (s *SCIMService) UpdateAttributeForSCIMUser(ctx context.Context, org, scimUserID string, opts *UpdateAttributeForSCIMUserOptions) (*Response, error) {
+	u := fmt.Sprintf("scim/v2/organizations/%v/Users/%v", org, scimUserID)
+	u, err := addOptions(u, opts)
+	if err != nil {
+		return nil, err
+	}
+	req, err := s.client.NewRequest("PATCH", u, nil)
+	if err != nil {
+		return nil, err
+	}
+	return s.client.Do(ctx, req, nil)
+}
+
+// DeleteSCIMUserFromOrg deletes SCIM user from an organization.
+//
+// GitHub API docs: https://docs.github.com/en/rest/reference/scim#delete-a-scim-user-from-an-organization
+func (s *SCIMService) DeleteSCIMUserFromOrg(ctx context.Context, org, scimUserID string) (*Response, error) {
+	u := fmt.Sprintf("scim/v2/organizations/%v/Users/%v", org, scimUserID)
+	req, err := s.client.NewRequest("DELETE", u, nil)
+	if err != nil {
+		return nil, err
+	}
+	return s.client.Do(ctx, req, nil)
+}


Test patch:
diff --git a/github/github-accessors_test.go b/github/github-accessors_test.go
index 92a22c7a..df604c44 100644
--- a/github/github-accessors_test.go
+++ b/github/github-accessors_test.go
@@ -1417,6 +1417,56 @@ func TestAuthorizationUpdateRequest_GetNoteURL(tt *testing.T) {
 	a.GetNoteURL()
 }
 
+func TestAutolink_GetID(tt *testing.T) {
+	var zeroValue int64
+	a := &Autolink{ID: &zeroValue}
+	a.GetID()
+	a = &Autolink{}
+	a.GetID()
+	a = nil
+	a.GetID()
+}
+
+func TestAutolink_GetKeyPrefix(tt *testing.T) {
+	var zeroValue string
+	a := &Autolink{KeyPrefix: &zeroValue}
+	a.GetKeyPrefix()
+	a = &Autolink{}
+	a.GetKeyPrefix()
+	a = nil
+	a.GetKeyPrefix()
+}
+
+func TestAutolink_GetURLTemplate(tt *testing.T) {
+	var zeroValue string
+	a := &Autolink{URLTemplate: &zeroValue}
+	a.GetURLTemplate()
+	a = &Autolink{}
+	a.GetURLTemplate()
+	a = nil
+	a.GetURLTemplate()
+}
+
+func TestAutolinkOptions_GetKeyPrefix(tt *testing.T) {
+	var zeroValue string
+	a := &AutolinkOptions{KeyPrefix: &zeroValue}
+	a.GetKeyPrefix()
+	a = &AutolinkOptions{}
+	a.GetKeyPrefix()
+	a = nil
+	a.GetKeyPrefix()
+}
+
+func TestAutolinkOptions_GetURLTemplate(tt *testing.T) {
+	var zeroValue string
+	a := &AutolinkOptions{URLTemplate: &zeroValue}
+	a.GetURLTemplate()
+	a = &AutolinkOptions{}
+	a.GetURLTemplate()
+	a = nil
+	a.GetURLTemplate()
+}
+
 func TestAutoTriggerCheck_GetAppID(tt *testing.T) {
 	var zeroValue int64
 	a := &AutoTriggerCheck{AppID: &zeroValue}
@@ -2941,6 +2991,13 @@ func TestCommunityHealthFiles_GetCodeOfConduct(tt *testing.T) {
 	c.GetCodeOfConduct()
 }
 
+func TestCommunityHealthFiles_GetCodeOfConductFile(tt *testing.T) {
+	c := &CommunityHealthFiles{}
+	c.GetCodeOfConductFile()
+	c = nil
+	c.GetCodeOfConductFile()
+}
+
 func TestCommunityHealthFiles_GetContributing(tt *testing.T) {
 	c := &CommunityHealthFiles{}
 	c.GetContributing()
@@ -2976,6 +3033,36 @@ func TestCommunityHealthFiles_GetReadme(tt *testing.T) {
 	c.GetReadme()
 }
 
+func TestCommunityHealthMetrics_GetContentReportsEnabled(tt *testing.T) {
+	var zeroValue bool
+	c := &CommunityHealthMetrics{ContentReportsEnabled: &zeroValue}
+	c.GetContentReportsEnabled()
+	c = &CommunityHealthMetrics{}
+	c.GetContentReportsEnabled()
+	c = nil
+	c.GetContentReportsEnabled()
+}
+
+func TestCommunityHealthMetrics_GetDescription(tt *testing.T) {
+	var zeroValue string
+	c := &CommunityHealthMetrics{Description: &zeroValue}
+	c.GetDescription()
+	c = &CommunityHealthMetrics{}
+	c.GetDescription()
+	c = nil
+	c.GetDescription()
+}
+
+func TestCommunityHealthMetrics_GetDocumentation(tt *testing.T) {
+	var zeroValue string
+	c := &CommunityHealthMetrics{Documentation: &zeroValue}
+	c.GetDocumentation()
+	c = &CommunityHealthMetrics{}
+	c.GetDocumentation()
+	c = nil
+	c.GetDocumentation()
+}
+
 func TestCommunityHealthMetrics_GetFiles(tt *testing.T) {
 	c := &CommunityHealthMetrics{}
 	c.GetFiles()
@@ -8427,6 +8514,36 @@ func TestListRepositories_GetTotalCount(tt *testing.T) {
 	l.GetTotalCount()
 }
 
+func TestListSCIMProvisionedIdentitiesOptions_GetCount(tt *testing.T) {
+	var zeroValue int
+	l := &ListSCIMProvisionedIdentitiesOptions{Count: &zeroValue}
+	l.GetCount()
+	l = &ListSCIMProvisionedIdentitiesOptions{}
+	l.GetCount()
+	l = nil
+	l.GetCount()
+}
+
+func TestListSCIMProvisionedIdentitiesOptions_GetFilter(tt *testing.T) {
+	var zeroValue string
+	l := &ListSCIMProvisionedIdentitiesOptions{Filter: &zeroValue}
+	l.GetFilter()
+	l = &ListSCIMProvisionedIdentitiesOptions{}
+	l.GetFilter()
+	l = nil
+	l.GetFilter()
+}
+
+func TestListSCIMProvisionedIdentitiesOptions_GetStartIndex(tt *testing.T) {
+	var zeroValue int
+	l := &ListSCIMProvisionedIdentitiesOptions{StartIndex: &zeroValue}
+	l.GetStartIndex()
+	l = &ListSCIMProvisionedIdentitiesOptions{}
+	l.GetStartIndex()
+	l = nil
+	l.GetStartIndex()
+}
+
 func TestLocation_GetEndColumn(tt *testing.T) {
 	var zeroValue int
 	l := &Location{EndColumn: &zeroValue}
@@ -9047,6 +9164,26 @@ func TestMetric_GetName(tt *testing.T) {
 	m.GetName()
 }
 
+func TestMetric_GetNodeID(tt *testing.T) {
+	var zeroValue string
+	m := &Metric{NodeID: &zeroValue}
+	m.GetNodeID()
+	m = &Metric{}
+	m.GetNodeID()
+	m = nil
+	m.GetNodeID()
+}
+
+func TestMetric_GetSPDXID(tt *testing.T) {
+	var zeroValue string
+	m := &Metric{SPDXID: &zeroValue}
+	m.GetSPDXID()
+	m = &Metric{}
+	m.GetSPDXID()
+	m = nil
+	m.GetSPDXID()
+}
+
 func TestMetric_GetURL(tt *testing.T) {
 	var zeroValue string
 	m := &Metric{URL: &zeroValue}
@@ -17056,6 +17193,66 @@ func TestRunnerLabels_GetType(tt *testing.T) {
 	r.GetType()
 }
 
+func TestSCIMUserAttributes_GetActive(tt *testing.T) {
+	var zeroValue bool
+	s := &SCIMUserAttributes{Active: &zeroValue}
+	s.GetActive()
+	s = &SCIMUserAttributes{}
+	s.GetActive()
+	s = nil
+	s.GetActive()
+}
+
+func TestSCIMUserAttributes_GetDisplayName(tt *testing.T) {
+	var zeroValue string
+	s := &SCIMUserAttributes{DisplayName: &zeroValue}
+	s.GetDisplayName()
+	s = &SCIMUserAttributes{}
+	s.GetDisplayName()
+	s = nil
+	s.GetDisplayName()
+}
+
+func TestSCIMUserAttributes_GetExternalID(tt *testing.T) {
+	var zeroValue string
+	s := &SCIMUserAttributes{ExternalID: &zeroValue}
+	s.GetExternalID()
+	s = &SCIMUserAttributes{}
+	s.GetExternalID()
+	s = nil
+	s.GetExternalID()
+}
+
+func TestSCIMUserEmail_GetPrimary(tt *testing.T) {
+	var zeroValue bool
+	s := &SCIMUserEmail{Primary: &zeroValue}
+	s.GetPrimary()
+	s = &SCIMUserEmail{}
+	s.GetPrimary()
+	s = nil
+	s.GetPrimary()
+}
+
+func TestSCIMUserEmail_GetType(tt *testing.T) {
+	var zeroValue string
+	s := &SCIMUserEmail{Type: &zeroValue}
+	s.GetType()
+	s = &SCIMUserEmail{}
+	s.GetType()
+	s = nil
+	s.GetType()
+}
+
+func TestSCIMUserName_GetFormatted(tt *testing.T) {
+	var zeroValue string
+	s := &SCIMUserName{Formatted: &zeroValue}
+	s.GetFormatted()
+	s = &SCIMUserName{}
+	s.GetFormatted()
+	s = nil
+	s.GetFormatted()
+}
+
 func TestSelectedReposList_GetTotalCount(tt *testing.T) {
 	var zeroValue int
 	s := &SelectedReposList{TotalCount: &zeroValue}
@@ -18857,6 +19054,16 @@ func TestTreeEntry_GetURL(tt *testing.T) {
 	t.GetURL()
 }
 
+func TestUpdateAttributeForSCIMUserOperations_GetPath(tt *testing.T) {
+	var zeroValue string
+	u := &UpdateAttributeForSCIMUserOperations{Path: &zeroValue}
+	u.GetPath()
+	u = &UpdateAttributeForSCIMUserOperations{}
+	u.GetPath()
+	u = nil
+	u.GetPath()
+}
+
 func TestUpdateCheckRunOptions_GetCompletedAt(tt *testing.T) {
 	var zeroValue Timestamp
 	u := &UpdateCheckRunOptions{CompletedAt: &zeroValue}
@@ -20468,6 +20675,44 @@ func TestWorkflowJob_GetURL(tt *testing.T) {
 	w.GetURL()
 }
 
+func TestWorkflowJobEvent_GetAction(tt *testing.T) {
+	var zeroValue string
+	w := &WorkflowJobEvent{Action: &zeroValue}
+	w.GetAction()
+	w = &WorkflowJobEvent{}
+	w.GetAction()
+	w = nil
+	w.GetAction()
+}
+
+func TestWorkflowJobEvent_GetOrg(tt *testing.T) {
+	w := &WorkflowJobEvent{}
+	w.GetOrg()
+	w = nil
+	w.GetOrg()
+}
+
+func TestWorkflowJobEvent_GetRepo(tt *testing.T) {
+	w := &WorkflowJobEvent{}
+	w.GetRepo()
+	w = nil
+	w.GetRepo()
+}
+
+func TestWorkflowJobEvent_GetSender(tt *testing.T) {
+	w := &WorkflowJobEvent{}
+	w.GetSender()
+	w = nil
+	w.GetSender()
+}
+
+func TestWorkflowJobEvent_GetWorkflowJob(tt *testing.T) {
+	w := &WorkflowJobEvent{}
+	w.GetWorkflowJob()
+	w = nil
+	w.GetWorkflowJob()
+}
+
 func TestWorkflowRun_GetArtifactsURL(tt *testing.T) {
 	var zeroValue string
 	w := &WorkflowRun{ArtifactsURL: &zeroValue}
diff --git a/github/messages_test.go b/github/messages_test.go
index 9880a2a5..da8c3331 100644
--- a/github/messages_test.go
+++ b/github/messages_test.go
@@ -450,6 +450,10 @@ func TestParseWebHook(t *testing.T) {
 			payload:     &WorkflowDispatchEvent{},
 			messageType: "workflow_dispatch",
 		},
+		{
+			payload:     &WorkflowJobEvent{},
+			messageType: "workflow_job",
+		},
 		{
 			payload:     &WorkflowRunEvent{},
 			messageType: "workflow_run",
diff --git a/github/orgs_hooks_deliveries_test.go b/github/orgs_hooks_deliveries_test.go
index c1efc527..cd0bd109 100644
--- a/github/orgs_hooks_deliveries_test.go
+++ b/github/orgs_hooks_deliveries_test.go
@@ -104,3 +104,47 @@ func TestOrganizationsService_GetHookDelivery_invalidOwner(t *testing.T) {
 	_, _, err := client.Organizations.GetHookDelivery(ctx, "%", 1, 1)
 	testURLParseError(t, err)
 }
+
+func TestOrganizationsService_RedeliverHookDelivery(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/orgs/o/hooks/1/deliveries/1/attempts", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "POST")
+		fmt.Fprint(w, `{"id":1}`)
+	})
+
+	ctx := context.Background()
+	hook, _, err := client.Organizations.RedeliverHookDelivery(ctx, "o", 1, 1)
+	if err != nil {
+		t.Errorf("Organizations.RedeliverHookDelivery returned error: %v", err)
+	}
+
+	want := &HookDelivery{ID: Int64(1)}
+	if !cmp.Equal(hook, want) {
+		t.Errorf("Organizations.RedeliverHookDelivery returned %+v, want %+v", hook, want)
+	}
+
+	const methodName = "Rede;overHookDelivery"
+	testBadOptions(t, methodName, func() (err error) {
+		_, _, err = client.Organizations.RedeliverHookDelivery(ctx, "\n", -1, -1)
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		got, resp, err := client.Organizations.RedeliverHookDelivery(ctx, "o", 1, 1)
+		if got != nil {
+			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+		}
+		return resp, err
+	})
+}
+
+func TestOrganizationsService_RedeliverHookDelivery_invalidOwner(t *testing.T) {
+	client, _, _, teardown := setup()
+	defer teardown()
+
+	ctx := context.Background()
+	_, _, err := client.Organizations.RedeliverHookDelivery(ctx, "%", 1, 1)
+	testURLParseError(t, err)
+}
diff --git a/github/repos_autolinks_test.go b/github/repos_autolinks_test.go
new file mode 100644
index 00000000..b6121d2c
--- /dev/null
+++ b/github/repos_autolinks_test.go
@@ -0,0 +1,154 @@
+// 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"
+	"encoding/json"
+	"fmt"
+	"net/http"
+	"testing"
+
+	"github.com/google/go-cmp/cmp"
+)
+
+func TestRepositoriesService_ListAutolinks(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/repos/o/r/autolinks", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "GET")
+		testFormValues(t, r, values{"page": "2"})
+		fmt.Fprintf(w, `[{"id":1, "key_prefix": "TICKET-", "url_template": "https://example.com/TICKET?query=<num>"}, {"id":2, "key_prefix": "STORY-", "url_template": "https://example.com/STORY?query=<num>"}]`)
+	})
+
+	opt := &ListOptions{
+		Page: 2,
+	}
+	ctx := context.Background()
+	autolinks, _, err := client.Repositories.ListAutolinks(ctx, "o", "r", opt)
+	if err != nil {
+		t.Errorf("Repositories.ListAutolinks returned error: %v", err)
+	}
+
+	want := []*Autolink{
+		{ID: Int64(1), KeyPrefix: String("TICKET-"), URLTemplate: String("https://example.com/TICKET?query=<num>")},
+		{ID: Int64(2), KeyPrefix: String("STORY-"), URLTemplate: String("https://example.com/STORY?query=<num>")},
+	}
+
+	if !cmp.Equal(autolinks, want) {
+		t.Errorf("Repositories.ListAutolinks returned %+v, want %+v", autolinks, want)
+	}
+
+	const methodName = "ListAutolinks"
+	testBadOptions(t, methodName, func() (err error) {
+		_, _, err = client.Repositories.ListAutolinks(ctx, "\n", "\n", opt)
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		got, resp, err := client.Repositories.ListAutolinks(ctx, "o", "r", opt)
+		if got != nil {
+			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+		}
+		return resp, err
+	})
+}
+
+func TestRepositoriesService_AddAutolink(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	opt := &AutolinkOptions{KeyPrefix: String("TICKET-"), URLTemplate: String("https://example.com/TICKET?query=<num>")}
+	mux.HandleFunc("/repos/o/r/autolinks", func(w http.ResponseWriter, r *http.Request) {
+		v := new(AutolinkOptions)
+		json.NewDecoder(r.Body).Decode(v)
+		testMethod(t, r, "POST")
+		if !cmp.Equal(v, opt) {
+			t.Errorf("Request body = %+v, want %+v", v, opt)
+		}
+		w.WriteHeader(http.StatusOK)
+		w.Write([]byte(`{"key_prefix": "TICKET-","url_template": "https://example.com/TICKET?query=<num>"}`))
+	})
+	ctx := context.Background()
+	autolink, _, err := client.Repositories.AddAutolink(ctx, "o", "r", opt)
+	if err != nil {
+		t.Errorf("Repositories.AddAutolink returned error: %v", err)
+	}
+	want := &Autolink{
+		KeyPrefix:   String("TICKET-"),
+		URLTemplate: String("https://example.com/TICKET?query=<num>"),
+	}
+
+	if !cmp.Equal(autolink, want) {
+		t.Errorf("AddAutolink returned %+v, want %+v", autolink, want)
+	}
+
+	const methodName = "AddAutolink"
+	testBadOptions(t, methodName, func() (err error) {
+		_, _, err = client.Repositories.AddAutolink(ctx, "\n", "\n", opt)
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		got, resp, err := client.Repositories.AddAutolink(ctx, "o", "r", opt)
+		if got != nil {
+			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+		}
+		return resp, err
+	})
+}
+
+func TestRepositoriesService_GetAutolink(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/repos/o/r/autolinks/1", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "GET")
+		fmt.Fprintf(w, `{"id":1, "key_prefix": "TICKET-", "url_template": "https://example.com/TICKET?query=<num>"}`)
+	})
+
+	ctx := context.Background()
+	autolink, _, err := client.Repositories.GetAutolink(ctx, "o", "r", 1)
+	if err != nil {
+		t.Errorf("Repositories.GetAutolink returned error: %v", err)
+	}
+
+	want := &Autolink{ID: Int64(1), KeyPrefix: String("TICKET-"), URLTemplate: String("https://example.com/TICKET?query=<num>")}
+	if !cmp.Equal(autolink, want) {
+		t.Errorf("Repositories.GetAutolink returned %+v, want %+v", autolink, want)
+	}
+
+	const methodName = "GetAutolink"
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		got, resp, err := client.Repositories.GetAutolink(ctx, "o", "r", 2)
+		if got != nil {
+			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+		}
+		return resp, err
+	})
+}
+
+func TestRepositoriesService_DeleteAutolink(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/repos/o/r/autolinks/1", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "DELETE")
+		w.WriteHeader(http.StatusNoContent)
+	})
+
+	ctx := context.Background()
+	_, err := client.Repositories.DeleteAutolink(ctx, "o", "r", 1)
+	if err != nil {
+		t.Errorf("Repositories.DeleteAutolink returned error: %v", err)
+	}
+
+	const methodName = "DeleteAutolink"
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		return client.Repositories.DeleteAutolink(ctx, "o", "r", 2)
+	})
+}
diff --git a/github/repos_community_health_test.go b/github/repos_community_health_test.go
index 24a62493..0031cdb7 100644
--- a/github/repos_community_health_test.go
+++ b/github/repos_community_health_test.go
@@ -21,9 +21,10 @@ func TestRepositoriesService_GetCommunityHealthMetrics(t *testing.T) {
 
 	mux.HandleFunc("/repos/o/r/community/profile", func(w http.ResponseWriter, r *http.Request) {
 		testMethod(t, r, "GET")
-		testHeader(t, r, "Accept", mediaTypeRepositoryCommunityHealthMetricsPreview)
 		fmt.Fprintf(w, `{
 				"health_percentage": 100,
+				"description": "My first repository on GitHub!",
+				"documentation": null,
 				"files": {
 					"code_of_conduct": {
 						"name": "Contributor Covenant",
@@ -31,22 +32,37 @@ func TestRepositoriesService_GetCommunityHealthMetrics(t *testing.T) {
 						"url": null,
 						"html_url": "https://github.com/octocat/Hello-World/blob/master/CODE_OF_CONDUCT.md"
 					},
+					"code_of_conduct_file": {
+						"url": "https://api.github.com/repos/octocat/Hello-World/contents/CODE_OF_CONDUCT.md",
+						"html_url": "https://github.com/octocat/Hello-World/blob/master/CODE_OF_CONDUCT.md"
+					},
 					"contributing": {
 						"url": "https://api.github.com/repos/octocat/Hello-World/contents/CONTRIBUTING",
 						"html_url": "https://github.com/octocat/Hello-World/blob/master/CONTRIBUTING"
 					},
+					"issue_template": {
+						"url": "https://api.github.com/repos/octocat/Hello-World/contents/ISSUE_TEMPLATE",
+						"html_url": "https://github.com/octocat/Hello-World/blob/master/ISSUE_TEMPLATE"
+					},
+					"pull_request_template": {
+						"url": "https://api.github.com/repos/octocat/Hello-World/contents/PULL_REQUEST_TEMPLATE",
+						"html_url": "https://github.com/octocat/Hello-World/blob/master/PULL_REQUEST_TEMPLATE"
+					},
 					"license": {
 						"name": "MIT License",
 						"key": "mit",
+						"spdx_id": "MIT",
 						"url": "https://api.github.com/licenses/mit",
-						"html_url": "https://github.com/octocat/Hello-World/blob/master/LICENSE"
+						"html_url": "https://github.com/octocat/Hello-World/blob/master/LICENSE",
+						"node_id": "MDc6TGljZW5zZW1pdA=="
 					},
 					"readme": {
 						"url": "https://api.github.com/repos/octocat/Hello-World/contents/README.md",
 						"html_url": "https://github.com/octocat/Hello-World/blob/master/README.md"
 					}
 				},
-				"updated_at": "2017-02-28T00:00:00Z"
+				"updated_at": "2017-02-28T00:00:00Z",
+				"content_reports_enabled": true
 			}`)
 	})
 
@@ -58,23 +74,39 @@ func TestRepositoriesService_GetCommunityHealthMetrics(t *testing.T) {
 
 	updatedAt := time.Date(2017, time.February, 28, 0, 0, 0, 0, time.UTC)
 	want := &CommunityHealthMetrics{
-		HealthPercentage: Int(100),
-		UpdatedAt:        &updatedAt,
+		HealthPercentage:      Int(100),
+		Description:           String("My first repository on GitHub!"),
+		UpdatedAt:             &updatedAt,
+		ContentReportsEnabled: Bool(true),
 		Files: &CommunityHealthFiles{
 			CodeOfConduct: &Metric{
 				Name:    String("Contributor Covenant"),
 				Key:     String("contributor_covenant"),
 				HTMLURL: String("https://github.com/octocat/Hello-World/blob/master/CODE_OF_CONDUCT.md"),
 			},
+			CodeOfConductFile: &Metric{
+				URL:     String("https://api.github.com/repos/octocat/Hello-World/contents/CODE_OF_CONDUCT.md"),
+				HTMLURL: String("https://github.com/octocat/Hello-World/blob/master/CODE_OF_CONDUCT.md"),
+			},
 			Contributing: &Metric{
 				URL:     String("https://api.github.com/repos/octocat/Hello-World/contents/CONTRIBUTING"),
 				HTMLURL: String("https://github.com/octocat/Hello-World/blob/master/CONTRIBUTING"),
 			},
+			IssueTemplate: &Metric{
+				URL:     String("https://api.github.com/repos/octocat/Hello-World/contents/ISSUE_TEMPLATE"),
+				HTMLURL: String("https://github.com/octocat/Hello-World/blob/master/ISSUE_TEMPLATE"),
+			},
+			PullRequestTemplate: &Metric{
+				URL:     String("https://api.github.com/repos/octocat/Hello-World/contents/PULL_REQUEST_TEMPLATE"),
+				HTMLURL: String("https://github.com/octocat/Hello-World/blob/master/PULL_REQUEST_TEMPLATE"),
+			},
 			License: &Metric{
 				Name:    String("MIT License"),
 				Key:     String("mit"),
+				SPDXID:  String("MIT"),
 				URL:     String("https://api.github.com/licenses/mit"),
 				HTMLURL: String("https://github.com/octocat/Hello-World/blob/master/LICENSE"),
+				NodeID:  String("MDc6TGljZW5zZW1pdA=="),
 			},
 			Readme: &Metric{
 				URL:     String("https://api.github.com/repos/octocat/Hello-World/contents/README.md"),
@@ -107,15 +139,19 @@ func TestMetric_Marshal(t *testing.T) {
 	r := &Metric{
 		Name:    String("name"),
 		Key:     String("key"),
+		SPDXID:  String("spdx_id"),
 		URL:     String("url"),
 		HTMLURL: String("hurl"),
+		NodeID:  String("node_id"),
 	}
 
 	want := `{
 		"name": "name",
 		"key": "key",
+		"spdx_id": "spdx_id",
 		"url": "url",
-		"html_url": "hurl"
+		"html_url": "hurl",
+		"node_id": "node_id"
 	}`
 
 	testJSONMarshal(t, r, want)
@@ -131,6 +167,12 @@ func TestCommunityHealthFiles_Marshal(t *testing.T) {
 			URL:     String("url"),
 			HTMLURL: String("hurl"),
 		},
+		CodeOfConductFile: &Metric{
+			Name:    String("name"),
+			Key:     String("key"),
+			URL:     String("url"),
+			HTMLURL: String("hurl"),
+		},
 		Contributing: &Metric{
 			Name:    String("name"),
 			Key:     String("key"),
@@ -152,8 +194,10 @@ func TestCommunityHealthFiles_Marshal(t *testing.T) {
 		License: &Metric{
 			Name:    String("name"),
 			Key:     String("key"),
+			SPDXID:  String("spdx_id"),
 			URL:     String("url"),
 			HTMLURL: String("hurl"),
+			NodeID:  String("node_id"),
 		},
 		Readme: &Metric{
 			Name:    String("name"),
@@ -170,6 +214,12 @@ func TestCommunityHealthFiles_Marshal(t *testing.T) {
 			"url": "url",
 			"html_url": "hurl"
 		},
+		"code_of_conduct_file": {
+			"name": "name",
+			"key": "key",
+                        "url": "url",
+                        "html_url": "hurl"
+                },
 		"contributing": {
 			"name": "name",
 			"key": "key",
@@ -191,8 +241,10 @@ func TestCommunityHealthFiles_Marshal(t *testing.T) {
 		"license": {
 			"name": "name",
 			"key": "key",
+			"spdx_id": "spdx_id",
 			"url": "url",
-			"html_url": "hurl"
+			"html_url": "hurl",
+			"node_id": "node_id"
 		},
 		"readme": {
 			"name": "name",
@@ -210,6 +262,8 @@ func TestCommunityHealthMetrics_Marshal(t *testing.T) {
 
 	r := &CommunityHealthMetrics{
 		HealthPercentage: Int(1),
+		Description:      String("desc"),
+		Documentation:    String("docs"),
 		Files: &CommunityHealthFiles{
 			CodeOfConduct: &Metric{
 				Name:    String("name"),
@@ -217,6 +271,12 @@ func TestCommunityHealthMetrics_Marshal(t *testing.T) {
 				URL:     String("url"),
 				HTMLURL: String("hurl"),
 			},
+			CodeOfConductFile: &Metric{
+				Name:    String("name"),
+				Key:     String("key"),
+				URL:     String("url"),
+				HTMLURL: String("hurl"),
+			},
 			Contributing: &Metric{
 				Name:    String("name"),
 				Key:     String("key"),
@@ -238,8 +298,10 @@ func TestCommunityHealthMetrics_Marshal(t *testing.T) {
 			License: &Metric{
 				Name:    String("name"),
 				Key:     String("key"),
+				SPDXID:  String("spdx_id"),
 				URL:     String("url"),
 				HTMLURL: String("hurl"),
+				NodeID:  String("node_id"),
 			},
 			Readme: &Metric{
 				Name:    String("name"),
@@ -248,11 +310,14 @@ func TestCommunityHealthMetrics_Marshal(t *testing.T) {
 				HTMLURL: String("hurl"),
 			},
 		},
-		UpdatedAt: &referenceTime,
+		UpdatedAt:             &referenceTime,
+		ContentReportsEnabled: Bool(true),
 	}
 
 	want := `{
 		"health_percentage": 1,
+		"description": "desc",
+		"documentation": "docs",
 		"files": {
 			"code_of_conduct": {
 				"name": "name",
@@ -260,6 +325,12 @@ func TestCommunityHealthMetrics_Marshal(t *testing.T) {
 				"url": "url",
 				"html_url": "hurl"
 			},
+			"code_of_conduct_file": {
+                                "name": "name",
+                                "key": "key",
+                                "url": "url",
+                                "html_url": "hurl"
+                        },
 			"contributing": {
 				"name": "name",
 				"key": "key",
@@ -281,8 +352,10 @@ func TestCommunityHealthMetrics_Marshal(t *testing.T) {
 			"license": {
 				"name": "name",
 				"key": "key",
+				"spdx_id": "spdx_id",
 				"url": "url",
-				"html_url": "hurl"
+				"html_url": "hurl",
+				"node_id": "node_id"
 			},
 			"readme": {
 				"name": "name",
@@ -291,7 +364,8 @@ func TestCommunityHealthMetrics_Marshal(t *testing.T) {
 				"html_url": "hurl"
 			}
 		},
-		"updated_at": ` + referenceTimeStr + `
+		"updated_at": ` + referenceTimeStr + `,
+		"content_reports_enabled": true
 	}`
 
 	testJSONMarshal(t, r, want)
diff --git a/github/repos_hooks_deliveries_test.go b/github/repos_hooks_deliveries_test.go
index 5c6fb86d..b970eb49 100644
--- a/github/repos_hooks_deliveries_test.go
+++ b/github/repos_hooks_deliveries_test.go
@@ -155,6 +155,7 @@ var hookDeliveryPayloadTypeToStruct = map[string]interface{}{
 	"user":                           &UserEvent{},
 	"watch":                          &WatchEvent{},
 	"workflow_dispatch":              &WorkflowDispatchEvent{},
+	"workflow_job":                   &WorkflowJobEvent{},
 	"workflow_run":                   &WorkflowRunEvent{},
 }
 
diff --git a/github/repos_hooks_test.go b/github/repos_hooks_test.go
index 7cee77b7..49b16e33 100644
--- a/github/repos_hooks_test.go
+++ b/github/repos_hooks_test.go
@@ -296,3 +296,263 @@ func TestRepositoriesService_TestHook_invalidOwner(t *testing.T) {
 	_, err := client.Repositories.TestHook(ctx, "%", "%", 1)
 	testURLParseError(t, err)
 }
+
+func TestBranchWebHookPayload_Marshal(t *testing.T) {
+	testJSONMarshal(t, &WebHookPayload{}, "{}")
+
+	v := &WebHookPayload{
+		Action: String("action"),
+		After:  String("after"),
+		Before: String("before"),
+		Commits: []*WebHookCommit{
+			{
+				Added: []string{"1", "2", "3"},
+				Author: &WebHookAuthor{
+					Email:    String("abc@gmail.com"),
+					Name:     String("abc"),
+					Username: String("abc_12"),
+				},
+				Committer: &WebHookAuthor{
+					Email:    String("abc@gmail.com"),
+					Name:     String("abc"),
+					Username: String("abc_12"),
+				},
+				ID:       String("1"),
+				Message:  String("WebHookCommit"),
+				Modified: []string{"abc", "efg", "erd"},
+				Removed:  []string{"cmd", "rti", "duv"},
+			},
+		},
+		Compare: String("compare"),
+		Created: Bool(true),
+		Forced:  Bool(false),
+		HeadCommit: &WebHookCommit{
+			Added: []string{"1", "2", "3"},
+			Author: &WebHookAuthor{
+				Email:    String("abc@gmail.com"),
+				Name:     String("abc"),
+				Username: String("abc_12"),
+			},
+			Committer: &WebHookAuthor{
+				Email:    String("abc@gmail.com"),
+				Name:     String("abc"),
+				Username: String("abc_12"),
+			},
+			ID:       String("1"),
+			Message:  String("WebHookCommit"),
+			Modified: []string{"abc", "efg", "erd"},
+			Removed:  []string{"cmd", "rti", "duv"},
+		},
+		Installation: &Installation{
+			ID: Int64(12),
+		},
+		Organization: &Organization{
+			ID: Int64(22),
+		},
+		Pusher: &User{
+			Login: String("rd@yahoo.com"),
+			ID:    Int64(112),
+		},
+		Repo: &Repository{
+			ID:     Int64(321),
+			NodeID: String("node_321"),
+		},
+		Sender: &User{
+			Login: String("st@gmail.com"),
+			ID:    Int64(202),
+		},
+	}
+
+	want := `{
+		"action": "action",
+		"after":  "after",
+		"before": "before",
+		"commits": [
+			{
+			"added":   ["1", "2", "3"],
+			"author":{
+				"email": "abc@gmail.com",
+				"name": "abc",
+				"username": "abc_12"
+			},
+			"committer": {
+				"email": "abc@gmail.com",
+				"name": "abc",
+				"username": "abc_12"
+			}, 
+			"id":       "1",
+			"message":  "WebHookCommit",
+			"modified": ["abc", "efg", "erd"],
+			"removed":  ["cmd", "rti", "duv"]
+			}
+		],
+		"compare": "compare",
+		"created": true,
+		"forced":  false,
+		"head_commit": {
+			"added":   ["1", "2", "3"],
+		"author":{
+			"email": "abc@gmail.com",
+			"name": "abc",
+			"username": "abc_12"
+		},
+		"committer": {
+			"email": "abc@gmail.com",
+			"name": "abc",
+			"username": "abc_12"
+		}, 
+		"id":       "1",
+		"message":  "WebHookCommit",
+		"modified": ["abc", "efg", "erd"],
+		"removed":  ["cmd", "rti", "duv"]
+		},
+		"installation": {
+			"id": 12
+		},
+		"organization": {
+			"id" : 22
+		},
+		"pusher":{
+			"login": "rd@yahoo.com",
+			"id": 112
+		},
+		"repository":{
+			"id": 321,
+			"node_id": "node_321"
+		},
+		"sender":{
+			"login": "st@gmail.com",
+			"id": 202
+		}
+	}`
+
+	testJSONMarshal(t, v, want)
+}
+
+func TestBranchWebHookAuthor_Marshal(t *testing.T) {
+	testJSONMarshal(t, &WebHookAuthor{}, "{}")
+
+	v := &WebHookAuthor{
+		Email:    String("abc@gmail.com"),
+		Name:     String("abc"),
+		Username: String("abc_12"),
+	}
+
+	want := `{
+			"email": "abc@gmail.com",
+			"name": "abc",
+			"username": "abc_12"
+	}`
+
+	testJSONMarshal(t, v, want)
+}
+
+func TestBranchWebHookCommit_Marshal(t *testing.T) {
+	testJSONMarshal(t, &WebHookCommit{}, "{}")
+
+	v := &WebHookCommit{
+		Added: []string{"1", "2", "3"},
+		Author: &WebHookAuthor{
+			Email:    String("abc@gmail.com"),
+			Name:     String("abc"),
+			Username: String("abc_12"),
+		},
+		Committer: &WebHookAuthor{
+			Email:    String("abc@gmail.com"),
+			Name:     String("abc"),
+			Username: String("abc_12"),
+		},
+		ID:       String("1"),
+		Message:  String("WebHookCommit"),
+		Modified: []string{"abc", "efg", "erd"},
+		Removed:  []string{"cmd", "rti", "duv"},
+	}
+
+	want := `{
+		"added":   ["1", "2", "3"],
+		"author":{
+			"email": "abc@gmail.com",
+			"name": "abc",
+			"username": "abc_12"
+		},
+		"committer": {
+			"email": "abc@gmail.com",
+			"name": "abc",
+			"username": "abc_12"
+		}, 
+		"id":       "1",
+		"message":  "WebHookCommit",
+		"modified": ["abc", "efg", "erd"],
+		"removed":  ["cmd", "rti", "duv"]
+	}`
+
+	testJSONMarshal(t, v, want)
+}
+
+func TestBranchCreateHookRequest_Marshal(t *testing.T) {
+	testJSONMarshal(t, &createHookRequest{}, "{}")
+
+	v := &createHookRequest{
+		Name:   "abc",
+		Events: []string{"1", "2", "3"},
+		Active: Bool(true),
+		Config: map[string]interface{}{
+			"thing": "@123",
+		},
+	}
+
+	want := `{
+		"name": "abc",
+		"active": true,
+		"events": ["1","2","3"],
+		"config":{
+			"thing": "@123"
+		}
+	}`
+
+	testJSONMarshal(t, v, want)
+}
+
+func TestBranchHook_Marshal(t *testing.T) {
+	testJSONMarshal(t, &Hook{}, "{}")
+
+	v := &Hook{
+		CreatedAt: &referenceTime,
+		UpdatedAt: &referenceTime,
+		URL:       String("url"),
+		ID:        Int64(1),
+		Type:      String("type"),
+		Name:      String("name"),
+		TestURL:   String("testurl"),
+		PingURL:   String("pingurl"),
+		LastResponse: map[string]interface{}{
+			"item": "item",
+		},
+		Config: map[string]interface{}{
+			"thing": "@123",
+		},
+		Events: []string{"1", "2", "3"},
+		Active: Bool(true),
+	}
+
+	want := `{
+		"created_at": ` + referenceTimeStr + `,
+		"updated_at": ` + referenceTimeStr + `,
+		"url": "url",
+		"id": 1,
+		"type": "type",
+		"name": "name",
+		"test_url": "testurl",
+		"ping_url": "pingurl",
+		"last_response":{
+			"item": "item"
+		},
+		"config":{
+			"thing": "@123"
+		},
+		"events": ["1","2","3"],
+		"active": true		
+	}`
+
+	testJSONMarshal(t, v, want)
+}
diff --git a/github/repos_invitations_test.go b/github/repos_invitations_test.go
index e05ff3cd..74bda793 100644
--- a/github/repos_invitations_test.go
+++ b/github/repos_invitations_test.go
@@ -111,3 +111,55 @@ func TestRepositoriesService_UpdateInvitation(t *testing.T) {
 		return resp, err
 	})
 }
+
+func TestRepositoryInvitation_Marshal(t *testing.T) {
+	testJSONMarshal(t, &RepositoryInvitation{}, "{}")
+
+	r := &RepositoryInvitation{
+		ID: Int64(1),
+		Repo: &Repository{
+			ID:   Int64(1),
+			Name: String("n"),
+			URL:  String("u"),
+		},
+		Invitee: &User{
+			ID:   Int64(1),
+			Name: String("n"),
+			URL:  String("u"),
+		},
+		Inviter: &User{
+			ID:   Int64(1),
+			Name: String("n"),
+			URL:  String("u"),
+		},
+		Permissions: String("p"),
+		CreatedAt:   &Timestamp{referenceTime},
+		URL:         String("u"),
+		HTMLURL:     String("h"),
+	}
+
+	want := `{
+		"id":1,
+		"repository":{
+			"id":1,
+			"name":"n",
+			"url":"u"
+		},
+		"invitee":{
+			"id":1,
+			"name":"n",
+			"url":"u"
+		},
+		"inviter":{
+			"id":1,
+			"name":"n",
+			"url":"u"
+		},
+		"permissions":"p",
+		"created_at":` + referenceTimeStr + `,
+		"url":"u",
+		"html_url":"h"
+	}`
+
+	testJSONMarshal(t, r, want)
+}
diff --git a/github/scim_test.go b/github/scim_test.go
new file mode 100644
index 00000000..3338a28a
--- /dev/null
+++ b/github/scim_test.go
@@ -0,0 +1,194 @@
+// 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"
+	"net/http"
+	"testing"
+)
+
+func TestSCIMService_ListSCIMProvisionedIdentities(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/scim/v2/organizations/o/Users", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "GET")
+		w.WriteHeader(http.StatusOK)
+	})
+
+	ctx := context.Background()
+	opts := &ListSCIMProvisionedIdentitiesOptions{}
+	_, err := client.SCIM.ListSCIMProvisionedIdentities(ctx, "o", opts)
+	if err != nil {
+		t.Errorf("SCIM.ListSCIMProvisionedIdentities returned error: %v", err)
+	}
+
+	const methodName = "ListSCIMProvisionedIdentities"
+	testBadOptions(t, methodName, func() (err error) {
+		_, err = client.SCIM.ListSCIMProvisionedIdentities(ctx, "\n", opts)
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		return client.SCIM.ListSCIMProvisionedIdentities(ctx, "o", opts)
+	})
+}
+
+func TestSCIMService_ProvisionAndInviteSCIMUser(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/scim/v2/organizations/o/Users", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "POST")
+		w.WriteHeader(http.StatusOK)
+	})
+
+	ctx := context.Background()
+	opts := &SCIMUserAttributes{
+		UserName: "userName",
+		Name: SCIMUserName{
+			GivenName:  "givenName",
+			FamilyName: "familyName",
+		},
+		Emails: []*SCIMUserEmail{
+			{
+				Value: "octocat@github.com",
+			},
+		},
+	}
+	_, err := client.SCIM.ProvisionAndInviteSCIMUser(ctx, "o", opts)
+	if err != nil {
+		t.Errorf("SCIM.ListSCIMProvisionedIdentities returned error: %v", err)
+	}
+
+	const methodName = "ProvisionAndInviteSCIMUser"
+	testBadOptions(t, methodName, func() (err error) {
+		_, err = client.SCIM.ProvisionAndInviteSCIMUser(ctx, "\n", opts)
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		return client.SCIM.ProvisionAndInviteSCIMUser(ctx, "o", opts)
+	})
+}
+
+func TestSCIMService_GetSCIMProvisioningInfoForUser(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/scim/v2/organizations/o/Users/123", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "GET")
+		w.WriteHeader(http.StatusOK)
+	})
+
+	ctx := context.Background()
+	_, err := client.SCIM.GetSCIMProvisioningInfoForUser(ctx, "o", "123")
+	if err != nil {
+		t.Errorf("SCIM.GetSCIMProvisioningInfoForUser returned error: %v", err)
+	}
+
+	const methodName = "GetSCIMProvisioningInfoForUser"
+	testBadOptions(t, methodName, func() error {
+		_, err := client.SCIM.GetSCIMProvisioningInfoForUser(ctx, "\n", "123")
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		return client.SCIM.GetSCIMProvisioningInfoForUser(ctx, "o", "123")
+	})
+}
+
+func TestSCIMService_UpdateProvisionedOrgMembership(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/scim/v2/organizations/o/Users/123", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "PUT")
+		w.WriteHeader(http.StatusOK)
+	})
+
+	ctx := context.Background()
+	opts := &SCIMUserAttributes{
+		UserName: "userName",
+		Name: SCIMUserName{
+			GivenName:  "givenName",
+			FamilyName: "familyName",
+		},
+		Emails: []*SCIMUserEmail{
+			{
+				Value: "octocat@github.com",
+			},
+		},
+	}
+	_, err := client.SCIM.UpdateProvisionedOrgMembership(ctx, "o", "123", opts)
+	if err != nil {
+		t.Errorf("SCIM.UpdateProvisionedOrgMembership returned error: %v", err)
+	}
+
+	const methodName = "UpdateProvisionedOrgMembership"
+	testBadOptions(t, methodName, func() error {
+		_, err := client.SCIM.UpdateProvisionedOrgMembership(ctx, "\n", "123", opts)
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		return client.SCIM.UpdateProvisionedOrgMembership(ctx, "o", "123", opts)
+	})
+}
+
+func TestSCIMService_UpdateAttributeForSCIMUser(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/scim/v2/organizations/o/Users/123", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "PATCH")
+		w.WriteHeader(http.StatusNoContent)
+	})
+
+	ctx := context.Background()
+	opts := &UpdateAttributeForSCIMUserOptions{}
+	_, err := client.SCIM.UpdateAttributeForSCIMUser(ctx, "o", "123", opts)
+	if err != nil {
+		t.Errorf("SCIM.UpdateAttributeForSCIMUser returned error: %v", err)
+	}
+
+	const methodName = "UpdateAttributeForSCIMUser"
+	testBadOptions(t, methodName, func() error {
+		_, err := client.SCIM.UpdateAttributeForSCIMUser(ctx, "\n", "123", opts)
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		return client.SCIM.UpdateAttributeForSCIMUser(ctx, "o", "123", opts)
+	})
+}
+
+func TestSCIMService_DeleteSCIMUserFromOrg(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/scim/v2/organizations/o/Users/123", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "DELETE")
+		w.WriteHeader(http.StatusNoContent)
+	})
+
+	ctx := context.Background()
+	_, err := client.SCIM.DeleteSCIMUserFromOrg(ctx, "o", "123")
+	if err != nil {
+		t.Errorf("SCIM.DeleteSCIMUserFromOrg returned error: %v", err)
+	}
+
+	const methodName = "DeleteSCIMUserFromOrg"
+	testBadOptions(t, methodName, func() error {
+		_, err := client.SCIM.DeleteSCIMUserFromOrg(ctx, "\n", "")
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		return client.SCIM.DeleteSCIMUserFromOrg(ctx, "o", "123")
+	})
+}