Repository: google/go-github (go)

Issue:
Support Secret Scanning endpoints
Add support to retrieve and update secret scanning alerts for an enterprise, organization or repository ([Secret Scanning API reference](https://docs.github.com/en/rest/reference/secret-scanning#list-secret-scanning-alerts-for-a-repository)).

This is useful to automate tasks around security analysis and reporting.

Pull request:
Add support for the secret scanning API
This PR adds support for the [Secret Scanning API](https://docs.github.com/en/rest/reference/secret-scanning). Includes all endpoints and structures listed on the API documentation.

Closes #2278 

Patch:
diff --git a/example/listenvironments/main.go b/example/listenvironments/main.go
new file mode 100644
index 00000000..11f9d802
--- /dev/null
+++ b/example/listenvironments/main.go
@@ -0,0 +1,53 @@
+// Copyright 2022 The go-github AUTHORS. All rights reserved.
+//
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// listenvironments is an example of how to use ListEnvironments method with EnvironmentListOptions.
+// It's runnable with the following command:
+// 		export GITHUB_TOKEN=your_token
+//		export GITHUB_REPOSITORY_OWNER=your_owner
+//		export GITHUB_REPOSITORY_NAME=your_repo
+//		go run .
+package main
+
+import (
+	"context"
+	"fmt"
+	"log"
+	"os"
+
+	"github.com/google/go-github/v42/github"
+	"golang.org/x/oauth2"
+)
+
+func main() {
+	token := os.Getenv("GITHUB_AUTH_TOKEN")
+	repo := os.Getenv("GITHUB_REPOSITORY_NAME")
+	owner := os.Getenv("GITHUB_REPOSITORY_OWNER")
+
+	if token == "" {
+		log.Fatal("Unauthorized: No token present")
+	}
+
+	ts := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: token})
+
+	ctx := context.Background()
+	tc := oauth2.NewClient(ctx, ts)
+	client := github.NewClient(tc)
+
+	expectedPageSize := 2
+
+	opts := &github.EnvironmentListOptions{ListOptions: github.ListOptions{PerPage: expectedPageSize}}
+	envResponse, _, err := client.Repositories.ListEnvironments(ctx, owner, repo, opts)
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	if len(envResponse.Environments) != expectedPageSize {
+		log.Fatal("Unexpected number of environments returned")
+	}
+
+	// The number of environments here should be equal to expectedPageSize
+	fmt.Printf("%d environments returned\n", len(envResponse.Environments))
+}
diff --git a/github/github-accessors.go b/github/github-accessors.go
index 4bc74e57..90b92334 100644
--- a/github/github-accessors.go
+++ b/github/github-accessors.go
@@ -15964,6 +15964,206 @@ func (s *SecretScanning) GetStatus() string {
 	return *s.Status
 }
 
+// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise.
+func (s *SecretScanningAlert) GetCreatedAt() Timestamp {
+	if s == nil || s.CreatedAt == nil {
+		return Timestamp{}
+	}
+	return *s.CreatedAt
+}
+
+// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise.
+func (s *SecretScanningAlert) GetHTMLURL() string {
+	if s == nil || s.HTMLURL == nil {
+		return ""
+	}
+	return *s.HTMLURL
+}
+
+// GetLocationsURL returns the LocationsURL field if it's non-nil, zero value otherwise.
+func (s *SecretScanningAlert) GetLocationsURL() string {
+	if s == nil || s.LocationsURL == nil {
+		return ""
+	}
+	return *s.LocationsURL
+}
+
+// GetNumber returns the Number field if it's non-nil, zero value otherwise.
+func (s *SecretScanningAlert) GetNumber() int {
+	if s == nil || s.Number == nil {
+		return 0
+	}
+	return *s.Number
+}
+
+// GetResolution returns the Resolution field if it's non-nil, zero value otherwise.
+func (s *SecretScanningAlert) GetResolution() string {
+	if s == nil || s.Resolution == nil {
+		return ""
+	}
+	return *s.Resolution
+}
+
+// GetResolvedAt returns the ResolvedAt field if it's non-nil, zero value otherwise.
+func (s *SecretScanningAlert) GetResolvedAt() Timestamp {
+	if s == nil || s.ResolvedAt == nil {
+		return Timestamp{}
+	}
+	return *s.ResolvedAt
+}
+
+// GetResolvedBy returns the ResolvedBy field.
+func (s *SecretScanningAlert) GetResolvedBy() *User {
+	if s == nil {
+		return nil
+	}
+	return s.ResolvedBy
+}
+
+// GetSecret returns the Secret field if it's non-nil, zero value otherwise.
+func (s *SecretScanningAlert) GetSecret() string {
+	if s == nil || s.Secret == nil {
+		return ""
+	}
+	return *s.Secret
+}
+
+// GetSecretType returns the SecretType field if it's non-nil, zero value otherwise.
+func (s *SecretScanningAlert) GetSecretType() string {
+	if s == nil || s.SecretType == nil {
+		return ""
+	}
+	return *s.SecretType
+}
+
+// GetState returns the State field if it's non-nil, zero value otherwise.
+func (s *SecretScanningAlert) GetState() string {
+	if s == nil || s.State == nil {
+		return ""
+	}
+	return *s.State
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (s *SecretScanningAlert) GetURL() string {
+	if s == nil || s.URL == nil {
+		return ""
+	}
+	return *s.URL
+}
+
+// GetDetails returns the Details field.
+func (s *SecretScanningAlertLocation) GetDetails() *SecretScanningAlertLocationDetails {
+	if s == nil {
+		return nil
+	}
+	return s.Details
+}
+
+// GetType returns the Type field if it's non-nil, zero value otherwise.
+func (s *SecretScanningAlertLocation) GetType() string {
+	if s == nil || s.Type == nil {
+		return ""
+	}
+	return *s.Type
+}
+
+// GetBlobSHA returns the BlobSHA field if it's non-nil, zero value otherwise.
+func (s *SecretScanningAlertLocationDetails) GetBlobSHA() string {
+	if s == nil || s.BlobSHA == nil {
+		return ""
+	}
+	return *s.BlobSHA
+}
+
+// GetBlobURL returns the BlobURL field if it's non-nil, zero value otherwise.
+func (s *SecretScanningAlertLocationDetails) GetBlobURL() string {
+	if s == nil || s.BlobURL == nil {
+		return ""
+	}
+	return *s.BlobURL
+}
+
+// GetCommitSHA returns the CommitSHA field if it's non-nil, zero value otherwise.
+func (s *SecretScanningAlertLocationDetails) GetCommitSHA() string {
+	if s == nil || s.CommitSHA == nil {
+		return ""
+	}
+	return *s.CommitSHA
+}
+
+// GetCommitURL returns the CommitURL field if it's non-nil, zero value otherwise.
+func (s *SecretScanningAlertLocationDetails) GetCommitURL() string {
+	if s == nil || s.CommitURL == nil {
+		return ""
+	}
+	return *s.CommitURL
+}
+
+// GetEndColumn returns the EndColumn field if it's non-nil, zero value otherwise.
+func (s *SecretScanningAlertLocationDetails) GetEndColumn() int {
+	if s == nil || s.EndColumn == nil {
+		return 0
+	}
+	return *s.EndColumn
+}
+
+// GetEndLine returns the EndLine field if it's non-nil, zero value otherwise.
+func (s *SecretScanningAlertLocationDetails) GetEndLine() int {
+	if s == nil || s.EndLine == nil {
+		return 0
+	}
+	return *s.EndLine
+}
+
+// GetPath returns the Path field if it's non-nil, zero value otherwise.
+func (s *SecretScanningAlertLocationDetails) GetPath() string {
+	if s == nil || s.Path == nil {
+		return ""
+	}
+	return *s.Path
+}
+
+// GetStartColumn returns the StartColumn field if it's non-nil, zero value otherwise.
+func (s *SecretScanningAlertLocationDetails) GetStartColumn() int {
+	if s == nil || s.StartColumn == nil {
+		return 0
+	}
+	return *s.StartColumn
+}
+
+// GetStartline returns the Startline field if it's non-nil, zero value otherwise.
+func (s *SecretScanningAlertLocationDetails) GetStartline() int {
+	if s == nil || s.Startline == nil {
+		return 0
+	}
+	return *s.Startline
+}
+
+// GetResolution returns the Resolution field if it's non-nil, zero value otherwise.
+func (s *SecretScanningAlertUpdateOptions) GetResolution() string {
+	if s == nil || s.Resolution == nil {
+		return ""
+	}
+	return *s.Resolution
+}
+
+// GetSecretType returns the SecretType field if it's non-nil, zero value otherwise.
+func (s *SecretScanningAlertUpdateOptions) GetSecretType() string {
+	if s == nil || s.SecretType == nil {
+		return ""
+	}
+	return *s.SecretType
+}
+
+// GetState returns the State field if it's non-nil, zero value otherwise.
+func (s *SecretScanningAlertUpdateOptions) GetState() string {
+	if s == nil || s.State == nil {
+		return ""
+	}
+	return *s.State
+}
+
 // GetAdvancedSecurity returns the AdvancedSecurity field.
 func (s *SecurityAndAnalysis) GetAdvancedSecurity() *AdvancedSecurity {
 	if s == nil {
diff --git a/github/github.go b/github/github.go
index 4fb466e3..e5d59400 100644
--- a/github/github.go
+++ b/github/github.go
@@ -196,6 +196,7 @@ type Client struct {
 	Repositories   *RepositoriesService
 	SCIM           *SCIMService
 	Search         *SearchService
+	SecretScanning *SecretScanningService
 	Teams          *TeamsService
 	Users          *UsersService
 }
@@ -325,6 +326,7 @@ func NewClient(httpClient *http.Client) *Client {
 	c.Repositories = (*RepositoriesService)(&c.common)
 	c.SCIM = (*SCIMService)(&c.common)
 	c.Search = (*SearchService)(&c.common)
+	c.SecretScanning = (*SecretScanningService)(&c.common)
 	c.Teams = (*TeamsService)(&c.common)
 	c.Users = (*UsersService)(&c.common)
 	return c
diff --git a/github/repos_environments.go b/github/repos_environments.go
index 25cb005e..5dd45428 100644
--- a/github/repos_environments.go
+++ b/github/repos_environments.go
@@ -63,6 +63,12 @@ type RequiredReviewer struct {
 	Reviewer interface{} `json:"reviewer,omitempty"`
 }
 
+// EnvironmentListOptions specifies the optional parameters to the
+// RepositoriesService.ListEnvironments method.
+type EnvironmentListOptions struct {
+	ListOptions
+}
+
 // UnmarshalJSON implements the json.Unmarshaler interface.
 // This helps us handle the fact that RequiredReviewer can have either a User or Team type reviewer field.
 func (r *RequiredReviewer) UnmarshalJSON(data []byte) error {
@@ -99,8 +105,12 @@ func (r *RequiredReviewer) UnmarshalJSON(data []byte) error {
 // ListEnvironments lists all environments for a repository.
 //
 // GitHub API docs: https://docs.github.com/en/rest/reference/repos#get-all-environments
-func (s *RepositoriesService) ListEnvironments(ctx context.Context, owner, repo string) (*EnvResponse, *Response, error) {
+func (s *RepositoriesService) ListEnvironments(ctx context.Context, owner, repo string, opts *EnvironmentListOptions) (*EnvResponse, *Response, error) {
 	u := fmt.Sprintf("repos/%s/%s/environments", owner, repo)
+	u, err := addOptions(u, opts)
+	if err != nil {
+		return nil, nil, err
+	}
 
 	req, err := s.client.NewRequest("GET", u, nil)
 	if err != nil {
diff --git a/github/secret_scanning.go b/github/secret_scanning.go
new file mode 100644
index 00000000..f5061f3b
--- /dev/null
+++ b/github/secret_scanning.go
@@ -0,0 +1,234 @@
+// Copyright 2022 The go-github AUTHORS. All rights reserved.
+//
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package github
+
+import (
+	"context"
+	"fmt"
+)
+
+// SecretScanningService handles communication with the secret scanning related
+// methods of the GitHub API.
+//
+// GitHub API docs: https://docs.github.com/en/rest/reference/secret-scanning
+type SecretScanningService service
+
+// SecretScanningAlert represents a GitHub secret scanning alert.
+type SecretScanningAlert struct {
+	Number       *int       `json:"number,omitempty"`
+	CreatedAt    *Timestamp `json:"created_at,omitempty"`
+	URL          *string    `json:"url,omitempty"`
+	HTMLURL      *string    `json:"html_url,omitempty"`
+	LocationsURL *string    `json:"locations_url,omitempty"`
+	State        *string    `json:"state,omitempty"`
+	Resolution   *string    `json:"resolution,omitempty"`
+	ResolvedAt   *Timestamp `json:"resolved_at,omitempty"`
+	ResolvedBy   *User      `json:"resolved_by,omitempty"`
+	SecretType   *string    `json:"secret_type,omitempty"`
+	Secret       *string    `json:"secret,omitempty"`
+}
+
+// SecretScanningAlertLocation represents the location for a secret scanning alert.
+type SecretScanningAlertLocation struct {
+	Type    *string                             `json:"type,omitempty"`
+	Details *SecretScanningAlertLocationDetails `json:"details,omitempty"`
+}
+
+// SecretScanningAlertLocationDetails represents the location details for a secret scanning alert.
+type SecretScanningAlertLocationDetails struct {
+	Path        *string `json:"path,omitempty"`
+	Startline   *int    `json:"start_line,omitempty"`
+	EndLine     *int    `json:"end_line,omitempty"`
+	StartColumn *int    `json:"start_column,omitempty"`
+	EndColumn   *int    `json:"end_column,omitempty"`
+	BlobSHA     *string `json:"blob_sha,omitempty"`
+	BlobURL     *string `json:"blob_url,omitempty"`
+	CommitSHA   *string `json:"commit_sha,omitempty"`
+	CommitURL   *string `json:"commit_url,omitempty"`
+}
+
+// SecretScanningAlertListOptions specifies optional parameters to the SecretScanningService.ListAlertsForEnterprise method.
+type SecretScanningAlertListOptions struct {
+	// State of the secret scanning alerts to list. Set to open or resolved to only list secret scanning alerts in a specific state.
+	State string `url:"state,omitempty"`
+
+	// A comma-separated list of secret types to return. By default all secret types are returned.
+	SecretType string `url:"secret_type,omitempty"`
+
+	// A comma-separated list of resolutions. Only secret scanning alerts with one of these resolutions are listed.
+	// Valid resolutions are false_positive, wont_fix, revoked, pattern_edited, pattern_deleted or used_in_tests.
+	Resolution string `url:"resolution,omitempty"`
+
+	ListCursorOptions
+}
+
+// SecretScanningAlertUpdateOptions specifies optional parameters to the SecretScanningService.UpdateAlert method.
+type SecretScanningAlertUpdateOptions struct {
+	// Required. Sets the state of the secret scanning alert. Can be either open or resolved.
+	// You must provide resolution when you set the state to resolved.
+	State *string `url:"state,omitempty"`
+
+	// A comma-separated list of secret types to return. By default all secret types are returned.
+	SecretType *string `url:"secret_type,omitempty"`
+
+	// Required when the state is resolved. The reason for resolving the alert. Can be one of false_positive,
+	// wont_fix, revoked, or used_in_tests.
+	Resolution *string `url:"resolution,omitempty"`
+}
+
+// Lists secret scanning alerts for eligible repositories in an enterprise, from newest to oldest.
+//
+// To use this endpoint, you must be a member of the enterprise, and you must use an access token with the repo scope or
+// security_events scope. Alerts are only returned for organizations in the enterprise for which you are an organization owner or a security manager.
+//
+// GitHub API docs: https://docs.github.com/en/rest/reference/secret-scanning#list-secret-scanning-alerts-for-an-enterprise
+func (s *SecretScanningService) ListAlertsForEnterprise(ctx context.Context, enterprise string, opts *SecretScanningAlertListOptions) ([]*SecretScanningAlert, *Response, error) {
+	u := fmt.Sprintf("enterprises/%v/secret-scanning/alerts", enterprise)
+	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 alerts []*SecretScanningAlert
+	resp, err := s.client.Do(ctx, req, &alerts)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return alerts, resp, nil
+}
+
+// Lists secret scanning alerts for eligible repositories in an organization, from newest to oldest.
+//
+// To use this endpoint, you must be an administrator for the repository or organization, and you must use an access token with
+// the repo scope or security_events scope.
+//
+// GitHub API docs: https://docs.github.com/en/rest/reference/secret-scanning#list-secret-scanning-alerts-for-an-organization
+func (s *SecretScanningService) ListAlertsForOrg(ctx context.Context, org string, opts *SecretScanningAlertListOptions) ([]*SecretScanningAlert, *Response, error) {
+	u := fmt.Sprintf("orgs/%v/secret-scanning/alerts", 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 alerts []*SecretScanningAlert
+	resp, err := s.client.Do(ctx, req, &alerts)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return alerts, resp, nil
+}
+
+// Lists secret scanning alerts for a private repository, from newest to oldest.
+//
+// To use this endpoint, you must be an administrator for the repository or organization, and you must use an access token with
+// the repo scope or security_events scope.
+//
+// GitHub API docs: https://docs.github.com/en/rest/reference/secret-scanning#list-secret-scanning-alerts-for-a-repository
+func (s *SecretScanningService) ListAlertsForRepo(ctx context.Context, owner, repo string, opts *SecretScanningAlertListOptions) ([]*SecretScanningAlert, *Response, error) {
+	u := fmt.Sprintf("repos/%v/%v/secret-scanning/alerts", 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 alerts []*SecretScanningAlert
+	resp, err := s.client.Do(ctx, req, &alerts)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return alerts, resp, nil
+}
+
+// Gets a single secret scanning alert detected in a private repository.
+//
+// To use this endpoint, you must be an administrator for the repository or organization, and you must use an access token with
+// the repo scope or security_events scope.
+//
+// GitHub API docs: https://docs.github.com/en/rest/reference/secret-scanning#get-a-secret-scanning-alert
+func (s *SecretScanningService) GetAlert(ctx context.Context, owner, repo string, number int64) (*SecretScanningAlert, *Response, error) {
+	u := fmt.Sprintf("repos/%v/%v/secret-scanning/alerts/%v", owner, repo, number)
+
+	req, err := s.client.NewRequest("GET", u, nil)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	var alert *SecretScanningAlert
+	resp, err := s.client.Do(ctx, req, &alert)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return alert, resp, nil
+}
+
+// Updates the status of a secret scanning alert in a private repository.
+//
+// To use this endpoint, you must be an administrator for the repository or organization, and you must use an access token with
+// the repo scope or security_events scope.
+//
+// GitHub API docs: https://docs.github.com/en/rest/reference/secret-scanning#update-a-secret-scanning-alert
+func (s *SecretScanningService) UpdateAlert(ctx context.Context, owner, repo string, number int64, opts *SecretScanningAlertUpdateOptions) (*SecretScanningAlert, *Response, error) {
+	u := fmt.Sprintf("repos/%v/%v/secret-scanning/alerts/%v", owner, repo, number)
+
+	req, err := s.client.NewRequest("PATCH", u, opts)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	var alert *SecretScanningAlert
+	resp, err := s.client.Do(ctx, req, &alert)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return alert, resp, nil
+}
+
+// Lists all locations for a given secret scanning alert for a private repository.
+//
+// To use this endpoint, you must be an administrator for the repository or organization, and you must use an access token with
+// the repo scope or security_events scope.
+//
+// GitHub API docs: https://docs.github.com/en/rest/reference/secret-scanning#list-locations-for-a-secret-scanning-alert
+func (s *SecretScanningService) ListLocationsForAlert(ctx context.Context, owner, repo string, number int64, opts *ListOptions) ([]*SecretScanningAlertLocation, *Response, error) {
+	u := fmt.Sprintf("repos/%v/%v/secret-scanning/alerts/%v/locations", owner, repo, number)
+	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 locations []*SecretScanningAlertLocation
+	resp, err := s.client.Do(ctx, req, &locations)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return locations, resp, nil
+}


Test patch:
diff --git a/github/github-accessors_test.go b/github/github-accessors_test.go
index 3c480f4e..df8754f5 100644
--- a/github/github-accessors_test.go
+++ b/github/github-accessors_test.go
@@ -18681,6 +18681,250 @@ func TestSecretScanning_GetStatus(tt *testing.T) {
 	s.GetStatus()
 }
 
+func TestSecretScanningAlert_GetCreatedAt(tt *testing.T) {
+	var zeroValue Timestamp
+	s := &SecretScanningAlert{CreatedAt: &zeroValue}
+	s.GetCreatedAt()
+	s = &SecretScanningAlert{}
+	s.GetCreatedAt()
+	s = nil
+	s.GetCreatedAt()
+}
+
+func TestSecretScanningAlert_GetHTMLURL(tt *testing.T) {
+	var zeroValue string
+	s := &SecretScanningAlert{HTMLURL: &zeroValue}
+	s.GetHTMLURL()
+	s = &SecretScanningAlert{}
+	s.GetHTMLURL()
+	s = nil
+	s.GetHTMLURL()
+}
+
+func TestSecretScanningAlert_GetLocationsURL(tt *testing.T) {
+	var zeroValue string
+	s := &SecretScanningAlert{LocationsURL: &zeroValue}
+	s.GetLocationsURL()
+	s = &SecretScanningAlert{}
+	s.GetLocationsURL()
+	s = nil
+	s.GetLocationsURL()
+}
+
+func TestSecretScanningAlert_GetNumber(tt *testing.T) {
+	var zeroValue int
+	s := &SecretScanningAlert{Number: &zeroValue}
+	s.GetNumber()
+	s = &SecretScanningAlert{}
+	s.GetNumber()
+	s = nil
+	s.GetNumber()
+}
+
+func TestSecretScanningAlert_GetResolution(tt *testing.T) {
+	var zeroValue string
+	s := &SecretScanningAlert{Resolution: &zeroValue}
+	s.GetResolution()
+	s = &SecretScanningAlert{}
+	s.GetResolution()
+	s = nil
+	s.GetResolution()
+}
+
+func TestSecretScanningAlert_GetResolvedAt(tt *testing.T) {
+	var zeroValue Timestamp
+	s := &SecretScanningAlert{ResolvedAt: &zeroValue}
+	s.GetResolvedAt()
+	s = &SecretScanningAlert{}
+	s.GetResolvedAt()
+	s = nil
+	s.GetResolvedAt()
+}
+
+func TestSecretScanningAlert_GetResolvedBy(tt *testing.T) {
+	s := &SecretScanningAlert{}
+	s.GetResolvedBy()
+	s = nil
+	s.GetResolvedBy()
+}
+
+func TestSecretScanningAlert_GetSecret(tt *testing.T) {
+	var zeroValue string
+	s := &SecretScanningAlert{Secret: &zeroValue}
+	s.GetSecret()
+	s = &SecretScanningAlert{}
+	s.GetSecret()
+	s = nil
+	s.GetSecret()
+}
+
+func TestSecretScanningAlert_GetSecretType(tt *testing.T) {
+	var zeroValue string
+	s := &SecretScanningAlert{SecretType: &zeroValue}
+	s.GetSecretType()
+	s = &SecretScanningAlert{}
+	s.GetSecretType()
+	s = nil
+	s.GetSecretType()
+}
+
+func TestSecretScanningAlert_GetState(tt *testing.T) {
+	var zeroValue string
+	s := &SecretScanningAlert{State: &zeroValue}
+	s.GetState()
+	s = &SecretScanningAlert{}
+	s.GetState()
+	s = nil
+	s.GetState()
+}
+
+func TestSecretScanningAlert_GetURL(tt *testing.T) {
+	var zeroValue string
+	s := &SecretScanningAlert{URL: &zeroValue}
+	s.GetURL()
+	s = &SecretScanningAlert{}
+	s.GetURL()
+	s = nil
+	s.GetURL()
+}
+
+func TestSecretScanningAlertLocation_GetDetails(tt *testing.T) {
+	s := &SecretScanningAlertLocation{}
+	s.GetDetails()
+	s = nil
+	s.GetDetails()
+}
+
+func TestSecretScanningAlertLocation_GetType(tt *testing.T) {
+	var zeroValue string
+	s := &SecretScanningAlertLocation{Type: &zeroValue}
+	s.GetType()
+	s = &SecretScanningAlertLocation{}
+	s.GetType()
+	s = nil
+	s.GetType()
+}
+
+func TestSecretScanningAlertLocationDetails_GetBlobSHA(tt *testing.T) {
+	var zeroValue string
+	s := &SecretScanningAlertLocationDetails{BlobSHA: &zeroValue}
+	s.GetBlobSHA()
+	s = &SecretScanningAlertLocationDetails{}
+	s.GetBlobSHA()
+	s = nil
+	s.GetBlobSHA()
+}
+
+func TestSecretScanningAlertLocationDetails_GetBlobURL(tt *testing.T) {
+	var zeroValue string
+	s := &SecretScanningAlertLocationDetails{BlobURL: &zeroValue}
+	s.GetBlobURL()
+	s = &SecretScanningAlertLocationDetails{}
+	s.GetBlobURL()
+	s = nil
+	s.GetBlobURL()
+}
+
+func TestSecretScanningAlertLocationDetails_GetCommitSHA(tt *testing.T) {
+	var zeroValue string
+	s := &SecretScanningAlertLocationDetails{CommitSHA: &zeroValue}
+	s.GetCommitSHA()
+	s = &SecretScanningAlertLocationDetails{}
+	s.GetCommitSHA()
+	s = nil
+	s.GetCommitSHA()
+}
+
+func TestSecretScanningAlertLocationDetails_GetCommitURL(tt *testing.T) {
+	var zeroValue string
+	s := &SecretScanningAlertLocationDetails{CommitURL: &zeroValue}
+	s.GetCommitURL()
+	s = &SecretScanningAlertLocationDetails{}
+	s.GetCommitURL()
+	s = nil
+	s.GetCommitURL()
+}
+
+func TestSecretScanningAlertLocationDetails_GetEndColumn(tt *testing.T) {
+	var zeroValue int
+	s := &SecretScanningAlertLocationDetails{EndColumn: &zeroValue}
+	s.GetEndColumn()
+	s = &SecretScanningAlertLocationDetails{}
+	s.GetEndColumn()
+	s = nil
+	s.GetEndColumn()
+}
+
+func TestSecretScanningAlertLocationDetails_GetEndLine(tt *testing.T) {
+	var zeroValue int
+	s := &SecretScanningAlertLocationDetails{EndLine: &zeroValue}
+	s.GetEndLine()
+	s = &SecretScanningAlertLocationDetails{}
+	s.GetEndLine()
+	s = nil
+	s.GetEndLine()
+}
+
+func TestSecretScanningAlertLocationDetails_GetPath(tt *testing.T) {
+	var zeroValue string
+	s := &SecretScanningAlertLocationDetails{Path: &zeroValue}
+	s.GetPath()
+	s = &SecretScanningAlertLocationDetails{}
+	s.GetPath()
+	s = nil
+	s.GetPath()
+}
+
+func TestSecretScanningAlertLocationDetails_GetStartColumn(tt *testing.T) {
+	var zeroValue int
+	s := &SecretScanningAlertLocationDetails{StartColumn: &zeroValue}
+	s.GetStartColumn()
+	s = &SecretScanningAlertLocationDetails{}
+	s.GetStartColumn()
+	s = nil
+	s.GetStartColumn()
+}
+
+func TestSecretScanningAlertLocationDetails_GetStartline(tt *testing.T) {
+	var zeroValue int
+	s := &SecretScanningAlertLocationDetails{Startline: &zeroValue}
+	s.GetStartline()
+	s = &SecretScanningAlertLocationDetails{}
+	s.GetStartline()
+	s = nil
+	s.GetStartline()
+}
+
+func TestSecretScanningAlertUpdateOptions_GetResolution(tt *testing.T) {
+	var zeroValue string
+	s := &SecretScanningAlertUpdateOptions{Resolution: &zeroValue}
+	s.GetResolution()
+	s = &SecretScanningAlertUpdateOptions{}
+	s.GetResolution()
+	s = nil
+	s.GetResolution()
+}
+
+func TestSecretScanningAlertUpdateOptions_GetSecretType(tt *testing.T) {
+	var zeroValue string
+	s := &SecretScanningAlertUpdateOptions{SecretType: &zeroValue}
+	s.GetSecretType()
+	s = &SecretScanningAlertUpdateOptions{}
+	s.GetSecretType()
+	s = nil
+	s.GetSecretType()
+}
+
+func TestSecretScanningAlertUpdateOptions_GetState(tt *testing.T) {
+	var zeroValue string
+	s := &SecretScanningAlertUpdateOptions{State: &zeroValue}
+	s.GetState()
+	s = &SecretScanningAlertUpdateOptions{}
+	s.GetState()
+	s = nil
+	s.GetState()
+}
+
 func TestSecurityAndAnalysis_GetAdvancedSecurity(tt *testing.T) {
 	s := &SecurityAndAnalysis{}
 	s.GetAdvancedSecurity()
diff --git a/github/repos_environments_test.go b/github/repos_environments_test.go
index 18a30ad6..59b3f8b4 100644
--- a/github/repos_environments_test.go
+++ b/github/repos_environments_test.go
@@ -108,8 +108,14 @@ func TestRepositoriesService_ListEnvironments(t *testing.T) {
 		fmt.Fprint(w, `{"total_count":1, "environments":[{"id":1}, {"id": 2}]}`)
 	})
 
+	opt := &EnvironmentListOptions{
+		ListOptions: ListOptions{
+			Page:    2,
+			PerPage: 2,
+		},
+	}
 	ctx := context.Background()
-	environments, _, err := client.Repositories.ListEnvironments(ctx, "o", "r")
+	environments, _, err := client.Repositories.ListEnvironments(ctx, "o", "r", opt)
 	if err != nil {
 		t.Errorf("Repositories.ListEnvironments returned error: %v", err)
 	}
@@ -120,12 +126,12 @@ func TestRepositoriesService_ListEnvironments(t *testing.T) {
 
 	const methodName = "ListEnvironments"
 	testBadOptions(t, methodName, func() (err error) {
-		_, _, err = client.Repositories.ListEnvironments(ctx, "\n", "\n")
+		_, _, err = client.Repositories.ListEnvironments(ctx, "\n", "\n", opt)
 		return err
 	})
 
 	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
-		got, resp, err := client.Repositories.ListEnvironments(ctx, "o", "r")
+		got, resp, err := client.Repositories.ListEnvironments(ctx, "o", "r", opt)
 		if got != nil {
 			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
 		}
diff --git a/github/secret_scanning_test.go b/github/secret_scanning_test.go
new file mode 100644
index 00000000..afe6144e
--- /dev/null
+++ b/github/secret_scanning_test.go
@@ -0,0 +1,410 @@
+// Copyright 2022 The go-github AUTHORS. All rights reserved.
+//
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package github
+
+import (
+	"context"
+	"encoding/json"
+	"fmt"
+	"net/http"
+	"testing"
+	"time"
+
+	"github.com/google/go-cmp/cmp"
+)
+
+func TestSecretScanningService_ListAlertsForEnterprise(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/enterprises/e/secret-scanning/alerts", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "GET")
+		testFormValues(t, r, values{"state": "open", "secret_type": "mailchimp_api_key"})
+
+		fmt.Fprint(w, `[{
+			"number": 1,
+			"created_at": "1996-06-20T00:00:00Z",
+			"url": "https://api.github.com/repos/o/r/secret-scanning/alerts/1",
+			"html_url": "https://github.com/o/r/security/secret-scanning/1",
+			"locations_url": "https://api.github.com/repos/o/r/secret-scanning/alerts/1/locations",
+			"state": "open",
+			"resolution": null,
+			"resolved_at": null,
+			"resolved_by": null,
+			"secret_type": "mailchimp_api_key",
+			"secret": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-us2"
+		}]`)
+	})
+
+	ctx := context.Background()
+	opts := &SecretScanningAlertListOptions{State: "open", SecretType: "mailchimp_api_key"}
+
+	alerts, _, err := client.SecretScanning.ListAlertsForEnterprise(ctx, "e", opts)
+	if err != nil {
+		t.Errorf("SecretScanning.ListAlertsForEnterprise returned error: %v", err)
+	}
+
+	date := Timestamp{time.Date(1996, time.June, 20, 00, 00, 00, 0, time.UTC)}
+	want := []*SecretScanningAlert{
+		{
+			Number:       Int(1),
+			CreatedAt:    &date,
+			URL:          String("https://api.github.com/repos/o/r/secret-scanning/alerts/1"),
+			HTMLURL:      String("https://github.com/o/r/security/secret-scanning/1"),
+			LocationsURL: String("https://api.github.com/repos/o/r/secret-scanning/alerts/1/locations"),
+			State:        String("open"),
+			Resolution:   nil,
+			ResolvedAt:   nil,
+			ResolvedBy:   nil,
+			SecretType:   String("mailchimp_api_key"),
+			Secret:       String("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-us2"),
+		},
+	}
+
+	if !cmp.Equal(alerts, want) {
+		t.Errorf("SecretScanning.ListAlertsForEnterprise returned %+v, want %+v", alerts, want)
+	}
+
+	const methodName = "ListAlertsForEnterprise"
+
+	testBadOptions(t, methodName, func() (err error) {
+		_, _, err = client.SecretScanning.ListAlertsForEnterprise(ctx, "\n", opts)
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		_, resp, err := client.SecretScanning.ListAlertsForEnterprise(ctx, "e", opts)
+		return resp, err
+	})
+}
+
+func TestSecretScanningService_ListAlertsForOrg(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/orgs/o/secret-scanning/alerts", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "GET")
+		testFormValues(t, r, values{"state": "open", "secret_type": "mailchimp_api_key"})
+
+		fmt.Fprint(w, `[{
+			"number": 1,
+			"created_at": "1996-06-20T00:00:00Z",
+			"url": "https://api.github.com/repos/o/r/secret-scanning/alerts/1",
+			"html_url": "https://github.com/o/r/security/secret-scanning/1",
+			"locations_url": "https://api.github.com/repos/o/r/secret-scanning/alerts/1/locations",
+			"state": "open",
+			"resolution": null,
+			"resolved_at": null,
+			"resolved_by": null,
+			"secret_type": "mailchimp_api_key",
+			"secret": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-us2"
+		}]`)
+	})
+
+	ctx := context.Background()
+	opts := &SecretScanningAlertListOptions{State: "open", SecretType: "mailchimp_api_key"}
+
+	alerts, _, err := client.SecretScanning.ListAlertsForOrg(ctx, "o", opts)
+	if err != nil {
+		t.Errorf("SecretScanning.ListAlertsForOrg returned error: %v", err)
+	}
+
+	date := Timestamp{time.Date(1996, time.June, 20, 00, 00, 00, 0, time.UTC)}
+	want := []*SecretScanningAlert{
+		{
+			Number:       Int(1),
+			CreatedAt:    &date,
+			URL:          String("https://api.github.com/repos/o/r/secret-scanning/alerts/1"),
+			HTMLURL:      String("https://github.com/o/r/security/secret-scanning/1"),
+			LocationsURL: String("https://api.github.com/repos/o/r/secret-scanning/alerts/1/locations"),
+			State:        String("open"),
+			Resolution:   nil,
+			ResolvedAt:   nil,
+			ResolvedBy:   nil,
+			SecretType:   String("mailchimp_api_key"),
+			Secret:       String("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-us2"),
+		},
+	}
+
+	if !cmp.Equal(alerts, want) {
+		t.Errorf("SecretScanning.ListAlertsForOrg returned %+v, want %+v", alerts, want)
+	}
+
+	const methodName = "ListAlertsForOrg"
+
+	testBadOptions(t, methodName, func() (err error) {
+		_, _, err = client.SecretScanning.ListAlertsForOrg(ctx, "\n", opts)
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		_, resp, err := client.SecretScanning.ListAlertsForOrg(ctx, "o", opts)
+		return resp, err
+	})
+}
+
+func TestSecretScanningService_ListAlertsForRepo(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/repos/o/r/secret-scanning/alerts", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "GET")
+		testFormValues(t, r, values{"state": "open", "secret_type": "mailchimp_api_key"})
+
+		fmt.Fprint(w, `[{
+			"number": 1,
+			"created_at": "1996-06-20T00:00:00Z",
+			"url": "https://api.github.com/repos/o/r/secret-scanning/alerts/1",
+			"html_url": "https://github.com/o/r/security/secret-scanning/1",
+			"locations_url": "https://api.github.com/repos/o/r/secret-scanning/alerts/1/locations",
+			"state": "open",
+			"resolution": null,
+			"resolved_at": null,
+			"resolved_by": null,
+			"secret_type": "mailchimp_api_key",
+			"secret": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-us2"
+		}]`)
+	})
+
+	ctx := context.Background()
+	opts := &SecretScanningAlertListOptions{State: "open", SecretType: "mailchimp_api_key"}
+
+	alerts, _, err := client.SecretScanning.ListAlertsForRepo(ctx, "o", "r", opts)
+	if err != nil {
+		t.Errorf("SecretScanning.ListAlertsForRepo returned error: %v", err)
+	}
+
+	date := Timestamp{time.Date(1996, time.June, 20, 00, 00, 00, 0, time.UTC)}
+	want := []*SecretScanningAlert{
+		{
+			Number:       Int(1),
+			CreatedAt:    &date,
+			URL:          String("https://api.github.com/repos/o/r/secret-scanning/alerts/1"),
+			HTMLURL:      String("https://github.com/o/r/security/secret-scanning/1"),
+			LocationsURL: String("https://api.github.com/repos/o/r/secret-scanning/alerts/1/locations"),
+			State:        String("open"),
+			Resolution:   nil,
+			ResolvedAt:   nil,
+			ResolvedBy:   nil,
+			SecretType:   String("mailchimp_api_key"),
+			Secret:       String("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-us2"),
+		},
+	}
+
+	if !cmp.Equal(alerts, want) {
+		t.Errorf("SecretScanning.ListAlertsForRepo returned %+v, want %+v", alerts, want)
+	}
+
+	const methodName = "ListAlertsForRepo"
+
+	testBadOptions(t, methodName, func() (err error) {
+		_, _, err = client.SecretScanning.ListAlertsForRepo(ctx, "\n", "\n", opts)
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		_, resp, err := client.SecretScanning.ListAlertsForRepo(ctx, "o", "r", opts)
+		return resp, err
+	})
+}
+
+func TestSecretScanningService_GetAlert(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/repos/o/r/secret-scanning/alerts/1", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "GET")
+
+		fmt.Fprint(w, `{
+			"number": 1,
+			"created_at": "1996-06-20T00:00:00Z",
+			"url": "https://api.github.com/repos/o/r/secret-scanning/alerts/1",
+			"html_url": "https://github.com/o/r/security/secret-scanning/1",
+			"locations_url": "https://api.github.com/repos/o/r/secret-scanning/alerts/1/locations",
+			"state": "open",
+			"resolution": null,
+			"resolved_at": null,
+			"resolved_by": null,
+			"secret_type": "mailchimp_api_key",
+			"secret": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-us2"
+		}`)
+	})
+
+	ctx := context.Background()
+
+	alert, _, err := client.SecretScanning.GetAlert(ctx, "o", "r", 1)
+	if err != nil {
+		t.Errorf("SecretScanning.GetAlert returned error: %v", err)
+	}
+
+	date := Timestamp{time.Date(1996, time.June, 20, 00, 00, 00, 0, time.UTC)}
+	want := &SecretScanningAlert{
+		Number:       Int(1),
+		CreatedAt:    &date,
+		URL:          String("https://api.github.com/repos/o/r/secret-scanning/alerts/1"),
+		HTMLURL:      String("https://github.com/o/r/security/secret-scanning/1"),
+		LocationsURL: String("https://api.github.com/repos/o/r/secret-scanning/alerts/1/locations"),
+		State:        String("open"),
+		Resolution:   nil,
+		ResolvedAt:   nil,
+		ResolvedBy:   nil,
+		SecretType:   String("mailchimp_api_key"),
+		Secret:       String("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-us2"),
+	}
+
+	if !cmp.Equal(alert, want) {
+		t.Errorf("SecretScanning.GetAlert returned %+v, want %+v", alert, want)
+	}
+
+	const methodName = "GetAlert"
+
+	testBadOptions(t, methodName, func() (err error) {
+		_, _, err = client.SecretScanning.GetAlert(ctx, "\n", "\n", 0)
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		_, resp, err := client.SecretScanning.GetAlert(ctx, "o", "r", 1)
+		return resp, err
+	})
+}
+
+func TestSecretScanningService_UpdateAlert(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/repos/o/r/secret-scanning/alerts/1", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "PATCH")
+
+		v := new(SecretScanningAlertUpdateOptions)
+		json.NewDecoder(r.Body).Decode(v)
+
+		want := &SecretScanningAlertUpdateOptions{State: String("resolved"), Resolution: String("used_in_tests")}
+
+		if !cmp.Equal(v, want) {
+			t.Errorf("Request body = %+v, want %+v", v, want)
+		}
+
+		fmt.Fprint(w, `{
+			"number": 1,
+			"created_at": "1996-06-20T00:00:00Z",
+			"url": "https://api.github.com/repos/o/r/secret-scanning/alerts/1",
+			"html_url": "https://github.com/o/r/security/secret-scanning/1",
+			"locations_url": "https://api.github.com/repos/o/r/secret-scanning/alerts/1/locations",
+			"state": "resolved",
+			"resolution": "used_in_tests",
+			"resolved_at": "1996-06-20T00:00:00Z",
+			"resolved_by": null,
+			"secret_type": "mailchimp_api_key",
+			"secret": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-us2"
+		}`)
+	})
+
+	ctx := context.Background()
+	opts := &SecretScanningAlertUpdateOptions{State: String("resolved"), Resolution: String("used_in_tests")}
+
+	alert, _, err := client.SecretScanning.UpdateAlert(ctx, "o", "r", 1, opts)
+	if err != nil {
+		t.Errorf("SecretScanning.UpdateAlert returned error: %v", err)
+	}
+
+	date := Timestamp{time.Date(1996, time.June, 20, 00, 00, 00, 0, time.UTC)}
+	want := &SecretScanningAlert{
+		Number:       Int(1),
+		CreatedAt:    &date,
+		URL:          String("https://api.github.com/repos/o/r/secret-scanning/alerts/1"),
+		HTMLURL:      String("https://github.com/o/r/security/secret-scanning/1"),
+		LocationsURL: String("https://api.github.com/repos/o/r/secret-scanning/alerts/1/locations"),
+		State:        String("resolved"),
+		Resolution:   String("used_in_tests"),
+		ResolvedAt:   &date,
+		ResolvedBy:   nil,
+		SecretType:   String("mailchimp_api_key"),
+		Secret:       String("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-us2"),
+	}
+
+	if !cmp.Equal(alert, want) {
+		t.Errorf("SecretScanning.UpdateAlert returned %+v, want %+v", alert, want)
+	}
+
+	const methodName = "UpdateAlert"
+
+	testBadOptions(t, methodName, func() (err error) {
+		_, _, err = client.SecretScanning.UpdateAlert(ctx, "\n", "\n", 1, opts)
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		_, resp, err := client.SecretScanning.UpdateAlert(ctx, "o", "r", 1, opts)
+		return resp, err
+	})
+}
+
+func TestSecretScanningService_ListLocationsForAlert(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/repos/o/r/secret-scanning/alerts/1/locations", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "GET")
+		testFormValues(t, r, values{"page": "1", "per_page": "100"})
+
+		fmt.Fprint(w, `[{
+			"type": "commit",
+			"details": {
+			  "path": "/example/secrets.txt",
+			  "start_line": 1,
+			  "end_line": 1,
+			  "start_column": 1,
+			  "end_column": 64,
+			  "blob_sha": "af5626b4a114abcb82d63db7c8082c3c4756e51b",
+			  "blob_url": "https://api.github.com/repos/o/r/git/blobs/af5626b4a114abcb82d63db7c8082c3c4756e51b",
+			  "commit_sha": "f14d7debf9775f957cf4f1e8176da0786431f72b",
+			  "commit_url": "https://api.github.com/repos/o/r/git/commits/f14d7debf9775f957cf4f1e8176da0786431f72b"
+			}
+		}]`)
+	})
+
+	ctx := context.Background()
+	opts := &ListOptions{Page: 1, PerPage: 100}
+
+	locations, _, err := client.SecretScanning.ListLocationsForAlert(ctx, "o", "r", 1, opts)
+	if err != nil {
+		t.Errorf("SecretScanning.ListLocationsForAlert returned error: %v", err)
+	}
+
+	want := []*SecretScanningAlertLocation{
+		{
+			Type: String("commit"),
+			Details: &SecretScanningAlertLocationDetails{
+				Path:        String("/example/secrets.txt"),
+				Startline:   Int(1),
+				EndLine:     Int(1),
+				StartColumn: Int(1),
+				EndColumn:   Int(64),
+				BlobSHA:     String("af5626b4a114abcb82d63db7c8082c3c4756e51b"),
+				BlobURL:     String("https://api.github.com/repos/o/r/git/blobs/af5626b4a114abcb82d63db7c8082c3c4756e51b"),
+				CommitSHA:   String("f14d7debf9775f957cf4f1e8176da0786431f72b"),
+				CommitURL:   String("https://api.github.com/repos/o/r/git/commits/f14d7debf9775f957cf4f1e8176da0786431f72b"),
+			},
+		},
+	}
+
+	if !cmp.Equal(locations, want) {
+		t.Errorf("SecretScanning.ListLocationsForAlert returned %+v, want %+v", locations, want)
+	}
+
+	const methodName = "ListLocationsForAlert"
+
+	testBadOptions(t, methodName, func() (err error) {
+		_, _, err = client.SecretScanning.ListLocationsForAlert(ctx, "\n", "\n", 1, opts)
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		_, resp, err := client.SecretScanning.ListLocationsForAlert(ctx, "o", "r", 1, opts)
+		return resp, err
+	})
+}