Repository: google/go-github
Pull request #2803 (2023-06-09 16:20:30)

Initial implementation of codespaces API
https://github.com/google/go-github/issues/2362

google-cla[bot]: Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this [failed invocation](https://github.com/google/go-github/pull/2803/checks?check_run_id=14141895356) of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.
artificial-aidan: > Nice job, @artificial-aidan! Just a few changes please, and then we will be ready for a second LGTM+Approval before merging.

I'll push those up. I also renamed some of the list methods to match others in the repo.
artificial-aidan: > Thank you! Please run "go generate ./..." in the top of the repo and push (not force-push) the changes to the PR. (...and also run gofmt, of course.) Also, please remember to sign the CLA. See CONTRIBUTING.md for more details.

Working on the CLA now.

Should I push the suggested changes, then run go generate?
codecov[bot]: ## [Codecov](https://app.codecov.io/gh/google/go-github/pull/2803?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google) Report
> Merging [#2803](https://app.codecov.io/gh/google/go-github/pull/2803?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google) (50a056c) into [master](https://app.codecov.io/gh/google/go-github/commit/3efdd2c7b3f7931e171d6e77e133ccd6e24ae0c5?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google) (3efdd2c) will **decrease** coverage by `0.04%`.
> The diff coverage is `92.68%`.

```diff
@@            Coverage Diff             @@
##           master    #2803      +/-   ##
==========================================
- Coverage   98.06%   98.02%   -0.04%     
==========================================
  Files         132      133       +1     
  Lines       11650    11732      +82     
==========================================
+ Hits        11424    11500      +76     
- Misses        154      158       +4     
- Partials       72       74       +2     
```


| [Impacted Files](https://app.codecov.io/gh/google/go-github/pull/2803?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google) | Coverage Δ | |
|---|---|---|
| [github/messages.go](https://app.codecov.io/gh/google/go-github/pull/2803?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google#diff-Z2l0aHViL21lc3NhZ2VzLmdv) | `100.00% <ø> (ø)` | |
| [github/codespaces.go](https://app.codecov.io/gh/google/go-github/pull/2803?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google#diff-Z2l0aHViL2NvZGVzcGFjZXMuZ28=) | `92.40% <92.40%> (ø)` | |
| [github/event.go](https://app.codecov.io/gh/google/go-github/pull/2803?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google#diff-Z2l0aHViL2V2ZW50Lmdv) | `100.00% <100.00%> (ø)` | |
| [github/github.go](https://app.codecov.io/gh/google/go-github/pull/2803?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google#diff-Z2l0aHViL2dpdGh1Yi5nbw==) | `97.97% <100.00%> (+<0.01%)` | :arrow_up: |


artificial-aidan: The last commit basically mirrors the functionality and layout of Action secrets, but consolidated the tests a bit. I added some examples I used when validating its functionality against a real github.
gmlewis: Please don't use force-push in this repo, as we always squash-and-merge at the end anyway.
It makes reviews on GitHub particularly painful to see what changed since the last review.
See CONTRIBUTING.md for more details.
artificial-aidan: > Please don't use force-push in this repo, as we always squash-and-merge at the end anyway. It makes reviews on GitHub particularly painful to see what changed since the last review. See CONTRIBUTING.md for more details.

Sorry about that. Must have been out of habit 👍 
gmlewis: It looks like you might need to run `gofmt` and `go generate ./...` again.

Patch:
diff --git a/README.md b/README.md
index 6858fd1a..9a5386c2 100644
--- a/README.md
+++ b/README.md
@@ -396,6 +396,7 @@ Versions prior to 48.2.0 are not listed.
 
 | go-github Version | GitHub v3 API Version |
 | ----------------- | --------------------- |
+| 53.1.0            | 2022-11-28            |
 | 53.0.0            | 2022-11-28            |
 | 52.0.0            | 2022-11-28            |
 | 51.0.0            | 2022-11-28            |
diff --git a/example/codespaces/newreposecretwithxcrypto/main.go b/example/codespaces/newreposecretwithxcrypto/main.go
new file mode 100644
index 00000000..fcc547b3
--- /dev/null
+++ b/example/codespaces/newreposecretwithxcrypto/main.go
@@ -0,0 +1,164 @@
+// Copyright 2023 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.
+
+// newreposecretwithxcrypto creates a new secret in GitHub for a given owner/repo.
+// newreposecretwithxcrypto uses x/crypto/nacl/box instead of sodium.
+// It does not depend on any native libraries and is easier to cross-compile for different platforms.
+// Quite possibly there is a performance penalty due to this.
+//
+// newreposecretwithxcrypto has two required flags for owner and repo, and takes in one argument for the name of the secret to add.
+// The secret value is pulled from an environment variable based on the secret name.
+// To authenticate with GitHub, provide your token via an environment variable GITHUB_AUTH_TOKEN.
+//
+// To verify the new secret, navigate to GitHub Repository > Settings > left side options bar > Secrets.
+//
+// Usage:
+//
+//	export GITHUB_AUTH_TOKEN=<auth token from github that has secret create rights>
+//	export SECRET_VARIABLE=<secret value of the secret variable>
+//	go run main.go -owner <owner name> -repo <repository name> SECRET_VARIABLE
+//
+// Example:
+//
+//	export GITHUB_AUTH_TOKEN=0000000000000000
+//	export SECRET_VARIABLE="my-secret"
+//	go run main.go -owner google -repo go-github SECRET_VARIABLE
+package main
+
+import (
+	"context"
+	crypto_rand "crypto/rand"
+	"encoding/base64"
+	"flag"
+	"fmt"
+	"log"
+	"os"
+
+	"github.com/google/go-github/v53/github"
+	"golang.org/x/crypto/nacl/box"
+)
+
+var (
+	repo  = flag.String("repo", "", "The repo that the secret should be added to, ex. go-github")
+	owner = flag.String("owner", "", "The owner of there repo this should be added to, ex. google")
+)
+
+func main() {
+	flag.Parse()
+
+	token := os.Getenv("GITHUB_AUTH_TOKEN")
+	if token == "" {
+		log.Fatal("please provide a GitHub API token via env variable GITHUB_AUTH_TOKEN")
+	}
+
+	if *repo == "" {
+		log.Fatal("please provide required flag --repo to specify GitHub repository ")
+	}
+
+	if *owner == "" {
+		log.Fatal("please provide required flag --owner to specify GitHub user/org owner")
+	}
+
+	secretName, err := getSecretName()
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	secretValue, err := getSecretValue(secretName)
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	ctx := context.Background()
+	client := github.NewTokenClient(ctx, token)
+
+	if err := addRepoSecret(ctx, client, *owner, *repo, secretName, secretValue); err != nil {
+		log.Fatal(err)
+	}
+
+	fmt.Printf("Added secret %q to the repo %v/%v\n", secretName, *owner, *repo)
+}
+
+func getSecretName() (string, error) {
+	secretName := flag.Arg(0)
+	if secretName == "" {
+		return "", fmt.Errorf("missing argument secret name")
+	}
+	return secretName, nil
+}
+
+func getSecretValue(secretName string) (string, error) {
+	secretValue := os.Getenv(secretName)
+	if secretValue == "" {
+		return "", fmt.Errorf("secret value not found under env variable %q", secretName)
+	}
+	return secretValue, nil
+}
+
+// addRepoSecret will add a secret to a GitHub repo for use in GitHub Codespaces.
+//
+// The secretName and secretValue will determine the name of the secret added and it's corresponding value.
+//
+// The actual transmission of the secret value to GitHub using the api requires that the secret value is encrypted
+// using the public key of the target repo. This encryption is done using x/crypto/nacl/box.
+//
+// First, the public key of the repo is retrieved. The public key comes base64
+// encoded, so it must be decoded prior to use.
+//
+// Second, the decode key is converted into a fixed size byte array.
+//
+// Third, the secret value is converted into a slice of bytes.
+//
+// Fourth, the secret is encrypted with box.SealAnonymous using the repo's decoded public key.
+//
+// Fifth, the encrypted secret is encoded as a base64 string to be used in a github.EncodedSecret type.
+//
+// Sixth, The other two properties of the github.EncodedSecret type are determined. The name of the secret to be added
+// (string not base64), and the KeyID of the public key used to encrypt the secret.
+// This can be retrieved via the public key's GetKeyID method.
+//
+// Finally, the github.EncodedSecret is passed into the GitHub client.Codespaces.CreateOrUpdateRepoSecret method to
+// populate the secret in the GitHub repo.
+func addRepoSecret(ctx context.Context, client *github.Client, owner string, repo, secretName string, secretValue string) error {
+	publicKey, _, err := client.Codespaces.GetRepoPublicKey(ctx, owner, repo)
+	if err != nil {
+		return err
+	}
+
+	encryptedSecret, err := encryptSecretWithPublicKey(publicKey, secretName, secretValue)
+	if err != nil {
+		return err
+	}
+
+	if _, err := client.Codespaces.CreateOrUpdateRepoSecret(ctx, owner, repo, encryptedSecret); err != nil {
+		return fmt.Errorf("Codespaces.CreateOrUpdateRepoSecret returned error: %v", err)
+	}
+
+	return nil
+}
+
+func encryptSecretWithPublicKey(publicKey *github.PublicKey, secretName string, secretValue string) (*github.EncryptedSecret, error) {
+	decodedPublicKey, err := base64.StdEncoding.DecodeString(publicKey.GetKey())
+	if err != nil {
+		return nil, fmt.Errorf("base64.StdEncoding.DecodeString was unable to decode public key: %v", err)
+	}
+
+	var boxKey [32]byte
+	copy(boxKey[:], decodedPublicKey)
+	secretBytes := []byte(secretValue)
+	encryptedBytes, err := box.SealAnonymous([]byte{}, secretBytes, &boxKey, crypto_rand.Reader)
+	if err != nil {
+		return nil, fmt.Errorf("box.SealAnonymous failed with error %w", err)
+	}
+
+	encryptedString := base64.StdEncoding.EncodeToString(encryptedBytes)
+	keyID := publicKey.GetKeyID()
+	encryptedSecret := &github.EncryptedSecret{
+		Name:           secretName,
+		KeyID:          keyID,
+		EncryptedValue: encryptedString,
+	}
+	return encryptedSecret, nil
+}
diff --git a/example/codespaces/newusersecretwithxcrypto/main.go b/example/codespaces/newusersecretwithxcrypto/main.go
new file mode 100644
index 00000000..dd230c1d
--- /dev/null
+++ b/example/codespaces/newusersecretwithxcrypto/main.go
@@ -0,0 +1,171 @@
+// Copyright 2023 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.
+
+// newusersecretwithxcrypto creates a new secret in GitHub for a given user.
+// newusersecretwithxcrypto uses x/crypto/nacl/box instead of sodium.
+// It does not depend on any native libraries and is easier to cross-compile for different platforms.
+// Quite possibly there is a performance penalty due to this.
+//
+// newusersecretwithxcrypto takes in one argument for the name of the secret to add, and 2 flags owner, repo.
+// If owner/repo are defined then it adds the secret to that repository
+// The secret value is pulled from an environment variable based on the secret name.
+// To authenticate with GitHub, provide your token via an environment variable GITHUB_AUTH_TOKEN.
+//
+// To verify the new secret, navigate to GitHub User > Settings > left side options bar > Codespaces > Secrets.
+//
+// Usage:
+//
+//	export GITHUB_AUTH_TOKEN=<auth token from github that has secret create rights>
+//	export SECRET_VARIABLE=<secret value of the secret variable>
+//	go run main.go SECRET_VARIABLE
+//
+// Example:
+//
+//	export GITHUB_AUTH_TOKEN=0000000000000000
+//	export SECRET_VARIABLE="my-secret"
+//	go run main.go SECRET_VARIABLE
+package main
+
+import (
+	"context"
+	crypto_rand "crypto/rand"
+	"encoding/base64"
+	"flag"
+	"fmt"
+	"log"
+	"os"
+
+	"github.com/google/go-github/v53/github"
+	"golang.org/x/crypto/nacl/box"
+)
+
+var (
+	repo  = flag.String("repo", "", "The repo that the secret should be added to, ex. go-github")
+	owner = flag.String("owner", "", "The owner of there repo this should be added to, ex. google")
+)
+
+func main() {
+	flag.Parse()
+
+	token := os.Getenv("GITHUB_AUTH_TOKEN")
+	if token == "" {
+		log.Fatal("please provide a GitHub API token via env variable GITHUB_AUTH_TOKEN")
+	}
+
+	secretName, err := getSecretName()
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	secretValue, err := getSecretValue(secretName)
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	ctx := context.Background()
+	client := github.NewTokenClient(ctx, token)
+
+	if err := addUserSecret(ctx, client, secretName, secretValue, *owner, *repo); err != nil {
+		log.Fatal(err)
+	}
+
+	fmt.Printf("Added secret %q to the authenticated user\n", secretName)
+}
+
+func getSecretName() (string, error) {
+	secretName := flag.Arg(0)
+	if secretName == "" {
+		return "", fmt.Errorf("missing argument secret name")
+	}
+	return secretName, nil
+}
+
+func getSecretValue(secretName string) (string, error) {
+	secretValue := os.Getenv(secretName)
+	if secretValue == "" {
+		return "", fmt.Errorf("secret value not found under env variable %q", secretName)
+	}
+	return secretValue, nil
+}
+
+// addUserSecret will add a secret to a GitHub user for use in GitHub Codespaces.
+//
+// The secretName and secretValue will determine the name of the secret added and it's corresponding value.
+//
+// The actual transmission of the secret value to GitHub using the api requires that the secret value is encrypted
+// using the public key of the target user. This encryption is done using x/crypto/nacl/box.
+//
+// First, the public key of the user is retrieved. The public key comes base64
+// encoded, so it must be decoded prior to use.
+//
+// Second, the decode key is converted into a fixed size byte array.
+//
+// Third, the secret value is converted into a slice of bytes.
+//
+// Fourth, the secret is encrypted with box.SealAnonymous using the user's decoded public key.
+//
+// Fifth, the encrypted secret is encoded as a base64 string to be used in a github.EncodedSecret type.
+//
+// Sixth, The other two properties of the github.EncodedSecret type are determined. The name of the secret to be added
+// (string not base64), and the KeyID of the public key used to encrypt the secret.
+// This can be retrieved via the public key's GetKeyID method.
+//
+// Seventh, the github.EncodedSecret is passed into the GitHub client.Codespaces.CreateOrUpdateUserSecret method to
+// populate the secret in the GitHub user.
+//
+// Finally, if a repo and owner are passed in, it adds the repo to the user secret.
+func addUserSecret(ctx context.Context, client *github.Client, secretName, secretValue, owner, repo string) error {
+	publicKey, _, err := client.Codespaces.GetUserPublicKey(ctx)
+	if err != nil {
+		return err
+	}
+
+	encryptedSecret, err := encryptSecretWithPublicKey(publicKey, secretName, secretValue)
+	if err != nil {
+		return err
+	}
+
+	if _, err := client.Codespaces.CreateOrUpdateUserSecret(ctx, encryptedSecret); err != nil {
+		return fmt.Errorf("Codespaces.CreateOrUpdateUserSecret returned error: %v", err)
+	}
+
+	if owner != "" && repo != "" {
+		r, _, err := client.Repositories.Get(ctx, owner, repo)
+		if err != nil {
+			return fmt.Errorf("Repositories.Get returned error: %v", err)
+		}
+		_, err = client.Codespaces.AddSelectedRepoToUserSecret(ctx, encryptedSecret.Name, r)
+		if err != nil {
+			return fmt.Errorf("Codespaces.AddSelectedRepoToUserSecret returned error: %v", err)
+		}
+		fmt.Printf("Added secret %q to %v/%v\n", secretName, owner, repo)
+	}
+
+	return nil
+}
+
+func encryptSecretWithPublicKey(publicKey *github.PublicKey, secretName string, secretValue string) (*github.EncryptedSecret, error) {
+	decodedPublicKey, err := base64.StdEncoding.DecodeString(publicKey.GetKey())
+	if err != nil {
+		return nil, fmt.Errorf("base64.StdEncoding.DecodeString was unable to decode public key: %v", err)
+	}
+
+	var boxKey [32]byte
+	copy(boxKey[:], decodedPublicKey)
+	secretBytes := []byte(secretValue)
+	encryptedBytes, err := box.SealAnonymous([]byte{}, secretBytes, &boxKey, crypto_rand.Reader)
+	if err != nil {
+		return nil, fmt.Errorf("box.SealAnonymous failed with error %w", err)
+	}
+
+	encryptedString := base64.StdEncoding.EncodeToString(encryptedBytes)
+	keyID := publicKey.GetKeyID()
+	encryptedSecret := &github.EncryptedSecret{
+		Name:           secretName,
+		KeyID:          keyID,
+		EncryptedValue: encryptedString,
+	}
+	return encryptedSecret, nil
+}
diff --git a/example/newreposecretwithxcrypto/main.go b/example/newreposecretwithxcrypto/main.go
index d6e32929..564fc069 100644
--- a/example/newreposecretwithxcrypto/main.go
+++ b/example/newreposecretwithxcrypto/main.go
@@ -99,7 +99,7 @@ func getSecretValue(secretName string) (string, error) {
 
 // addRepoSecret will add a secret to a GitHub repo for use in GitHub Actions.
 //
-// Finally, the secretName and secretValue will determine the name of the secret added and it's corresponding value.
+// The secretName and secretValue will determine the name of the secret added and it's corresponding value.
 //
 // The actual transmission of the secret value to GitHub using the api requires that the secret value is encrypted
 // using the public key of the target repo. This encryption is done using x/crypto/nacl/box.
@@ -115,7 +115,7 @@ func getSecretValue(secretName string) (string, error) {
 //
 // Fifth, the encrypted secret is encoded as a base64 string to be used in a github.EncodedSecret type.
 //
-// Sixt, The other two properties of the github.EncodedSecret type are determined. The name of the secret to be added
+// Sixth, The other two properties of the github.EncodedSecret type are determined. The name of the secret to be added
 // (string not base64), and the KeyID of the public key used to encrypt the secret.
 // This can be retrieved via the public key's GetKeyID method.
 //
diff --git a/github/actions_runners.go b/github/actions_runners.go
index 40c6be3a..3990a5a9 100644
--- a/github/actions_runners.go
+++ b/github/actions_runners.go
@@ -45,6 +45,60 @@ func (s *ActionsService) ListRunnerApplicationDownloads(ctx context.Context, own
 	return rads, resp, nil
 }
 
+// GenerateJITConfigRequest specifies body parameters to GenerateRepoJITConfig.
+type GenerateJITConfigRequest struct {
+	Name          string  `json:"name"`
+	RunnerGroupID int64   `json:"runner_group_id"`
+	WorkFolder    *string `json:"work_folder,omitempty"`
+
+	// Labels represents the names of the custom labels to add to the runner.
+	// Minimum items: 1. Maximum items: 100.
+	Labels []string `json:"labels"`
+}
+
+// JITRunnerConfig represents encoded JIT configuration that can be used to bootstrap a self-hosted runner.
+type JITRunnerConfig struct {
+	EncodedJITConfig *string `json:"encoded_jit_config,omitempty"`
+}
+
+// GenerateOrgJITConfig generate a just-in-time configuration for an organization.
+//
+// GitHub API docs: https://docs.github.com/en/rest/actions/self-hosted-runners?apiVersion=2022-11-28#create-configuration-for-a-just-in-time-runner-for-an-organization
+func (s *ActionsService) GenerateOrgJITConfig(ctx context.Context, owner string, request *GenerateJITConfigRequest) (*JITRunnerConfig, *Response, error) {
+	u := fmt.Sprintf("orgs/%v/actions/runners/generate-jitconfig", owner)
+	req, err := s.client.NewRequest("POST", u, request)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	jitConfig := new(JITRunnerConfig)
+	resp, err := s.client.Do(ctx, req, jitConfig)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return jitConfig, resp, nil
+}
+
+// GenerateRepoJITConfig generates a just-in-time configuration for a repository.
+//
+// GitHub API docs: https://docs.github.com/en/rest/actions/self-hosted-runners?apiVersion=2022-11-28#create-configuration-for-a-just-in-time-runner-for-a-repository
+func (s *ActionsService) GenerateRepoJITConfig(ctx context.Context, owner, repo string, request *GenerateJITConfigRequest) (*JITRunnerConfig, *Response, error) {
+	u := fmt.Sprintf("repos/%v/%v/actions/runners/generate-jitconfig", owner, repo)
+	req, err := s.client.NewRequest("POST", u, request)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	jitConfig := new(JITRunnerConfig)
+	resp, err := s.client.Do(ctx, req, jitConfig)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return jitConfig, resp, nil
+}
+
 // RegistrationToken represents a token that can be used to add a self-hosted runner to a repository.
 type RegistrationToken struct {
 	Token     *string    `json:"token,omitempty"`
diff --git a/github/code-scanning.go b/github/code-scanning.go
index 6717348e..e4a6abeb 100644
--- a/github/code-scanning.go
+++ b/github/code-scanning.go
@@ -378,3 +378,76 @@ func (s *CodeScanningService) GetAnalysis(ctx context.Context, owner, repo strin
 
 	return analysis, resp, nil
 }
+
+// DefaultSetupConfiguration represents a code scanning default setup configuration.
+type DefaultSetupConfiguration struct {
+	State      *string    `json:"state,omitempty"`
+	Languages  []string   `json:"languages,omitempty"`
+	QuerySuite *string    `json:"query_suite,omitempty"`
+	UpdatedAt  *Timestamp `json:"updated_at,omitempty"`
+}
+
+// GetDefaultSetupConfiguration gets a code scanning default setup configuration.
+//
+// You must use an access token with the repo scope to use this
+// endpoint with private repos or the public_repo scope for public repos. GitHub Apps must have the repo write
+// permission to use this endpoint.
+//
+// GitHub API docs: https://docs.github.com/en/rest/code-scanning#get-a-code-scanning-default-setup-configuration
+func (s *CodeScanningService) GetDefaultSetupConfiguration(ctx context.Context, owner, repo string) (*DefaultSetupConfiguration, *Response, error) {
+	u := fmt.Sprintf("repos/%s/%s/code-scanning/default-setup", owner, repo)
+
+	req, err := s.client.NewRequest("GET", u, nil)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	cfg := new(DefaultSetupConfiguration)
+	resp, err := s.client.Do(ctx, req, cfg)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return cfg, resp, nil
+}
+
+// UpdateDefaultSetupConfigurationOptions specifies parameters to the CodeScanningService.UpdateDefaultSetupConfiguration
+// method.
+type UpdateDefaultSetupConfigurationOptions struct {
+	State      string   `json:"state"`
+	QuerySuite *string  `json:"query_suite,omitempty"`
+	Languages  []string `json:"languages,omitempty"`
+}
+
+// UpdateDefaultSetupConfigurationResponse represents a response from updating a code scanning default setup configuration.
+type UpdateDefaultSetupConfigurationResponse struct {
+	RunID  *int64  `json:"run_id,omitempty"`
+	RunURL *string `json:"run_url,omitempty"`
+}
+
+// UpdateDefaultSetupConfiguration updates a code scanning default setup configuration.
+//
+// You must use an access token with the repo scope to use this
+// endpoint with private repos or the public_repo scope for public repos. GitHub Apps must have the repo write
+// permission to use this endpoint.
+//
+// This method might return an AcceptedError and a status code of 202. This is because this is the status that GitHub
+// returns to signify that it has now scheduled the update of the pull request branch in a background task.
+//
+// GitHub API docs: https://docs.github.com/en/rest/code-scanning#update-a-code-scanning-default-setup-configuration
+func (s *CodeScanningService) UpdateDefaultSetupConfiguration(ctx context.Context, owner, repo string, options *UpdateDefaultSetupConfigurationOptions) (*UpdateDefaultSetupConfigurationResponse, *Response, error) {
+	u := fmt.Sprintf("repos/%s/%s/code-scanning/default-setup", owner, repo)
+
+	req, err := s.client.NewRequest("PATCH", u, options)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	a := new(UpdateDefaultSetupConfigurationResponse)
+	resp, err := s.client.Do(ctx, req, a)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return a, resp, nil
+}
diff --git a/github/codespaces.go b/github/codespaces.go
new file mode 100644
index 00000000..a260c227
--- /dev/null
+++ b/github/codespaces.go
@@ -0,0 +1,254 @@
+// Copyright 2023 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"
+)
+
+// CodespacesService handles communication with the Codespaces related
+// methods of the GitHub API.
+//
+// GitHub API docs: https://docs.github.com/en/rest/codespaces/
+type CodespacesService service
+
+// Codespace represents a codespace.
+//
+// GitHub API docs: https://docs.github.com/en/rest/codespaces
+type Codespace struct {
+	ID                             *int64                        `json:"id,omitempty"`
+	Name                           *string                       `json:"name,omitempty"`
+	DisplayName                    *string                       `json:"display_name,omitempty"`
+	EnvironmentID                  *string                       `json:"environment_id,omitempty"`
+	Owner                          *User                         `json:"owner,omitempty"`
+	BillableOwner                  *User                         `json:"billable_owner,omitempty"`
+	Repository                     *Repository                   `json:"repository,omitempty"`
+	Machine                        *CodespacesMachine            `json:"machine,omitempty"`
+	DevcontainerPath               *string                       `json:"devcontainer_path,omitempty"`
+	Prebuild                       *bool                         `json:"prebuild,omitempty"`
+	CreatedAt                      *Timestamp                    `json:"created_at,omitempty"`
+	UpdatedAt                      *Timestamp                    `json:"updated_at,omitempty"`
+	LastUsedAt                     *Timestamp                    `json:"last_used_at,omitempty"`
+	State                          *string                       `json:"state,omitempty"`
+	URL                            *string                       `json:"url,omitempty"`
+	GitStatus                      *CodespacesGitStatus          `json:"git_status,omitempty"`
+	Location                       *string                       `json:"location,omitempty"`
+	IdleTimeoutMinutes             *int                          `json:"idle_timeout_minutes,omitempty"`
+	WebURL                         *string                       `json:"web_url,omitempty"`
+	MachinesURL                    *string                       `json:"machines_url,omitempty"`
+	StartURL                       *string                       `json:"start_url,omitempty"`
+	StopURL                        *string                       `json:"stop_url,omitempty"`
+	PullsURL                       *string                       `json:"pulls_url,omitempty"`
+	RecentFolders                  []string                      `json:"recent_folders,omitempty"`
+	RuntimeConstraints             *CodespacesRuntimeConstraints `json:"runtime_constraints,omitempty"`
+	PendingOperation               *bool                         `json:"pending_operation,omitempty"`
+	PendingOperationDisabledReason *string                       `json:"pending_operation_disabled_reason,omitempty"`
+	IdleTimeoutNotice              *string                       `json:"idle_timeout_notice,omitempty"`
+	RetentionPeriodMinutes         *int                          `json:"retention_period_minutes,omitempty"`
+	RetentionExpiresAt             *Timestamp                    `json:"retention_expires_at,omitempty"`
+	LastKnownStopNotice            *string                       `json:"last_known_stop_notice,omitempty"`
+}
+
+// CodespacesGitStatus represents the git status of a codespace.
+type CodespacesGitStatus struct {
+	Ahead                 *int    `json:"ahead,omitempty"`
+	Behind                *int    `json:"behind,omitempty"`
+	HasUnpushedChanges    *bool   `json:"has_unpushed_changes,omitempty"`
+	HasUncommittedChanges *bool   `json:"has_uncommitted_changes,omitempty"`
+	Ref                   *string `json:"ref,omitempty"`
+}
+
+// CodespacesMachine represents the machine type of a codespace.
+type CodespacesMachine struct {
+	Name                 *string `json:"name,omitempty"`
+	DisplayName          *string `json:"display_name,omitempty"`
+	OperatingSystem      *string `json:"operating_system,omitempty"`
+	StorageInBytes       *int64  `json:"storage_in_bytes,omitempty"`
+	MemoryInBytes        *int64  `json:"memory_in_bytes,omitempty"`
+	CPUs                 *int    `json:"cpus,omitempty"`
+	PrebuildAvailability *string `json:"prebuild_availability,omitempty"`
+}
+
+// CodespacesRuntimeConstraints represents the runtime constraints of a codespace.
+type CodespacesRuntimeConstraints struct {
+	AllowedPortPrivacySettings []string `json:"allowed_port_privacy_settings,omitempty"`
+}
+
+// ListCodespaces represents the response from the list codespaces endpoints.
+type ListCodespaces struct {
+	TotalCount *int         `json:"total_count,omitempty"`
+	Codespaces []*Codespace `json:"codespaces"`
+}
+
+// ListInRepo lists codespaces for a user in a repository.
+//
+// Lists the codespaces associated with a specified repository and the authenticated user.
+// You must authenticate using an access token with the codespace scope to use this endpoint.
+// GitHub Apps must have read access to the codespaces repository permission to use this endpoint.
+//
+// GitHub API docs: https://docs.github.com/en/rest/codespaces/codespaces?apiVersion=2022-11-28#list-codespaces-in-a-repository-for-the-authenticated-user
+func (s *CodespacesService) ListInRepo(ctx context.Context, owner, repo string, opts *ListOptions) (*ListCodespaces, *Response, error) {
+	u := fmt.Sprintf("repos/%v/%v/codespaces", 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 codespaces *ListCodespaces
+	resp, err := s.client.Do(ctx, req, &codespaces)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return codespaces, resp, nil
+}
+
+// ListOptions represents the options for listing codespaces for a user.
+type ListCodespacesOptions struct {
+	ListOptions
+	RepositoryID int64 `url:"repository_id,omitempty"`
+}
+
+// List lists codespaces for an authenticated user.
+//
+// Lists the authenticated user's codespaces.
+// You must authenticate using an access token with the codespace scope to use this endpoint.
+// GitHub Apps must have read access to the codespaces repository permission to use this endpoint.
+//
+// GitHub API docs: https://docs.github.com/en/rest/codespaces/codespaces?apiVersion=2022-11-28#list-codespaces-for-the-authenticated-user
+func (s *CodespacesService) List(ctx context.Context, opts *ListCodespacesOptions) (*ListCodespaces, *Response, error) {
+	u := fmt.Sprint("user/codespaces")
+	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 codespaces *ListCodespaces
+	resp, err := s.client.Do(ctx, req, &codespaces)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return codespaces, resp, nil
+}
+
+// CreateCodespaceOptions represents options for the creation of a codespace in a repository.
+type CreateCodespaceOptions struct {
+	Ref *string `json:"ref,omitempty"`
+	// Geo represents the geographic area for this codespace.
+	// If not specified, the value is assigned by IP.
+	// This property replaces location, which is being deprecated.
+	// Geo can be one of: `EuropeWest`, `SoutheastAsia`, `UsEast`, `UsWest`.
+	Geo                        *string `json:"geo,omitempty"`
+	ClientIP                   *string `json:"client_ip,omitempty"`
+	Machine                    *string `json:"machine,omitempty"`
+	DevcontainerPath           *string `json:"devcontainer_path,omitempty"`
+	MultiRepoPermissionsOptOut *bool   `json:"multi_repo_permissions_opt_out,omitempty"`
+	WorkingDirectory           *string `json:"working_directory,omitempty"`
+	IdleTimeoutMinutes         *int    `json:"idle_timeout_minutes,omitempty"`
+	DisplayName                *string `json:"display_name,omitempty"`
+	// RetentionPeriodMinutes represents the duration in minutes after codespace has gone idle in which it will be deleted.
+	// Must be integer minutes between 0 and 43200 (30 days).
+	RetentionPeriodMinutes *int `json:"retention_period_minutes,omitempty"`
+}
+
+// CreateInRepo creates a codespace in a repository.
+//
+// Creates a codespace owned by the authenticated user in the specified repository.
+// You must authenticate using an access token with the codespace scope to use this endpoint.
+// GitHub Apps must have write access to the codespaces repository permission to use this endpoint.
+//
+// GitHub API docs: https://docs.github.com/en/rest/codespaces/codespaces?apiVersion=2022-11-28#create-a-codespace-in-a-repository
+func (s *CodespacesService) CreateInRepo(ctx context.Context, owner, repo string, request *CreateCodespaceOptions) (*Codespace, *Response, error) {
+	u := fmt.Sprintf("repos/%v/%v/codespaces", owner, repo)
+
+	req, err := s.client.NewRequest("POST", u, request)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	var codespace *Codespace
+	resp, err := s.client.Do(ctx, req, &codespace)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return codespace, resp, nil
+}
+
+// Start starts a codespace.
+//
+// You must authenticate using an access token with the codespace scope to use this endpoint.
+// GitHub Apps must have write access to the codespaces_lifecycle_admin repository permission to use this endpoint.
+//
+// GitHub API docs: https://docs.github.com/en/rest/codespaces/codespaces?apiVersion=2022-11-28#start-a-codespace-for-the-authenticated-user
+func (s *CodespacesService) Start(ctx context.Context, codespaceName string) (*Codespace, *Response, error) {
+	u := fmt.Sprintf("user/codespaces/%v/start", codespaceName)
+
+	req, err := s.client.NewRequest("POST", u, nil)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	var codespace *Codespace
+	resp, err := s.client.Do(ctx, req, &codespace)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return codespace, resp, nil
+}
+
+// Stop stops a codespace.
+//
+// You must authenticate using an access token with the codespace scope to use this endpoint.
+// GitHub Apps must have write access to the codespaces_lifecycle_admin repository permission to use this endpoint.
+//
+// GitHub API docs: https://docs.github.com/en/rest/codespaces/codespaces?apiVersion=2022-11-28#stop-a-codespace-for-the-authenticated-user
+func (s *CodespacesService) Stop(ctx context.Context, codespaceName string) (*Codespace, *Response, error) {
+	u := fmt.Sprintf("user/codespaces/%v/stop", codespaceName)
+
+	req, err := s.client.NewRequest("POST", u, nil)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	var codespace *Codespace
+	resp, err := s.client.Do(ctx, req, &codespace)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return codespace, resp, nil
+}
+
+// Delete deletes a codespace.
+//
+// You must authenticate using an access token with the codespace scope to use this endpoint.
+// GitHub Apps must have write access to the codespaces repository permission to use this endpoint.
+//
+// GitHub API docs: https://docs.github.com/en/rest/codespaces/codespaces?apiVersion=2022-11-28#delete-a-codespace-for-the-authenticated-user
+func (s *CodespacesService) Delete(ctx context.Context, codespaceName string) (*Response, error) {
+	u := fmt.Sprintf("user/codespaces/%v", codespaceName)
+
+	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/codespaces_secrets.go b/github/codespaces_secrets.go
new file mode 100644
index 00000000..e11c679c
--- /dev/null
+++ b/github/codespaces_secrets.go
@@ -0,0 +1,405 @@
+// Copyright 2023 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"
+)
+
+// ListUserSecrets list all secrets available for a users codespace
+//
+// Lists all secrets available for a user's Codespaces without revealing their encrypted values
+// You must authenticate using an access token with the codespace or codespace:secrets scope to use this endpoint. User must have Codespaces access to use this endpoint
+// GitHub Apps must have read access to the codespaces_user_secrets user permission to use this endpoint.
+//
+// GitHub API docs: https://docs.github.com/en/rest/codespaces/secrets?apiVersion=2022-11-28#list-secrets-for-the-authenticated-user
+func (s *CodespacesService) ListUserSecrets(ctx context.Context, opts *ListOptions) (*Secrets, *Response, error) {
+	u, err := addOptions("user/codespaces/secrets", opts)
+	if err != nil {
+		return nil, nil, err
+	}
+	return s.listSecrets(ctx, u)
+}
+
+// ListOrgSecrets list all secrets available to an org
+//
+// Lists all Codespaces secrets available at the organization-level without revealing their encrypted values. You must authenticate using an access token with the admin:org scope to use this endpoint.
+//
+// GitHub API docs: https://docs.github.com/en/rest/codespaces/organization-secrets?apiVersion=2022-11-28#list-organization-secrets
+func (s *CodespacesService) ListOrgSecrets(ctx context.Context, org string, opts *ListOptions) (*Secrets, *Response, error) {
+	u := fmt.Sprintf("orgs/%v/codespaces/secrets", org)
+	u, err := addOptions(u, opts)
+	if err != nil {
+		return nil, nil, err
+	}
+	return s.listSecrets(ctx, u)
+}
+
+// ListRepoSecrets list all secrets available to a repo
+//
+// Lists all secrets available in a repository without revealing their encrypted values. You must authenticate using an access token with the repo scope to use this endpoint. GitHub Apps must have write access to the codespaces_secrets repository permission to use this endpoint.
+//
+// GitHub API docs: https://docs.github.com/en/rest/codespaces/repository-secrets?apiVersion=2022-11-28#list-repository-secrets
+func (s *CodespacesService) ListRepoSecrets(ctx context.Context, owner, repo string, opts *ListOptions) (*Secrets, *Response, error) {
+	u := fmt.Sprintf("repos/%v/%v/codespaces/secrets", owner, repo)
+	u, err := addOptions(u, opts)
+	if err != nil {
+		return nil, nil, err
+	}
+	return s.listSecrets(ctx, u)
+}
+
+func (s *CodespacesService) listSecrets(ctx context.Context, url string) (*Secrets, *Response, error) {
+	req, err := s.client.NewRequest("GET", url, nil)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	var secrets *Secrets
+	resp, err := s.client.Do(ctx, req, &secrets)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return secrets, resp, nil
+}
+
+// GetUserPublicKey gets the users public key for encrypting codespace secrets
+//
+// Gets your public key, which you need to encrypt secrets. You need to encrypt a secret before you can create or update secrets.
+// You must authenticate using an access token with the codespace or codespace:secrets scope to use this endpoint. User must have Codespaces access to use this endpoint.
+// GitHub Apps must have read access to the codespaces_user_secrets user permission to use this endpoint.
+//
+// GitHub API docs: https://docs.github.com/en/rest/codespaces/secrets?apiVersion=2022-11-28#get-public-key-for-the-authenticated-user
+func (s *CodespacesService) GetUserPublicKey(ctx context.Context) (*PublicKey, *Response, error) {
+	return s.getPublicKey(ctx, "user/codespaces/secrets/public-key")
+}
+
+// GetOrgPublicKey gets the org public key for encrypting codespace secrets
+//
+// Gets a public key for an organization, which is required in order to encrypt secrets. You need to encrypt the value of a secret before you can create or update secrets. You must authenticate using an access token with the admin:org scope to use this endpoint.
+//
+// GitHub API docs: https://docs.github.com/en/rest/codespaces/organization-secrets?apiVersion=2022-11-28#get-an-organization-public-key
+func (s *CodespacesService) GetOrgPublicKey(ctx context.Context, org string) (*PublicKey, *Response, error) {
+	return s.getPublicKey(ctx, fmt.Sprintf("orgs/%v/codespaces/secrets/public-key", org))
+}
+
+// GetRepoPublicKey gets the repo public key for encrypting codespace secrets
+//
+// Gets your public key, which you need to encrypt secrets. You need to encrypt a secret before you can create or update secrets. Anyone with read access to the repository can use this endpoint. If the repository is private you must use an access token with the repo scope. GitHub Apps must have write access to the codespaces_secrets repository permission to use this endpoint.
+//
+// GitHub API docs: https://docs.github.com/en/rest/codespaces/repository-secrets?apiVersion=2022-11-28#get-a-repository-public-key
+func (s *CodespacesService) GetRepoPublicKey(ctx context.Context, owner, repo string) (*PublicKey, *Response, error) {
+	return s.getPublicKey(ctx, fmt.Sprintf("repos/%v/%v/codespaces/secrets/public-key", owner, repo))
+}
+
+func (s *CodespacesService) getPublicKey(ctx context.Context, url string) (*PublicKey, *Response, error) {
+	req, err := s.client.NewRequest("GET", url, nil)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	var publicKey *PublicKey
+	resp, err := s.client.Do(ctx, req, &publicKey)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return publicKey, resp, nil
+}
+
+// GetUserSecret gets a users codespace secret
+//
+// Gets a secret available to a user's codespaces without revealing its encrypted value.
+// You must authenticate using an access token with the codespace or codespace:secrets scope to use this endpoint. User must have Codespaces access to use this endpoint.
+// GitHub Apps must have read access to the codespaces_user_secrets user permission to use this endpoint.
+//
+// GitHub API docs: https://docs.github.com/en/rest/codespaces/secrets?apiVersion=2022-11-28#get-a-secret-for-the-authenticated-user
+func (s *CodespacesService) GetUserSecret(ctx context.Context, name string) (*Secret, *Response, error) {
+	u := fmt.Sprintf("user/codespaces/secrets/%v", name)
+	return s.getSecret(ctx, u)
+}
+
+// GetOrgSecret gets an org codespace secret
+//
+// Gets an organization secret without revealing its encrypted value. You must authenticate using an access token with the admin:org scope to use this endpoint.
+//
+// GitHub API docs: https://docs.github.com/en/rest/codespaces/organization-secrets?apiVersion=2022-11-28#get-an-organization-secret
+func (s *CodespacesService) GetOrgSecret(ctx context.Context, org, name string) (*Secret, *Response, error) {
+	u := fmt.Sprintf("orgs/%v/codespaces/secrets/%v", org, name)
+	return s.getSecret(ctx, u)
+}
+
+// GetRepoSecret gets a repo codespace secret
+//
+// Gets a single repository secret without revealing its encrypted value. You must authenticate using an access token with the repo scope to use this endpoint. GitHub Apps must have write access to the codespaces_secrets repository permission to use this endpoint.
+//
+// GitHub API docs: https://docs.github.com/en/rest/codespaces/repository-secrets?apiVersion=2022-11-28#get-a-repository-secret
+func (s *CodespacesService) GetRepoSecret(ctx context.Context, owner, repo, name string) (*Secret, *Response, error) {
+	u := fmt.Sprintf("repos/%v/%v/codespaces/secrets/%v", owner, repo, name)
+	return s.getSecret(ctx, u)
+}
+
+func (s *CodespacesService) getSecret(ctx context.Context, url string) (*Secret, *Response, error) {
+	req, err := s.client.NewRequest("GET", url, nil)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	var secret *Secret
+	resp, err := s.client.Do(ctx, req, &secret)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return secret, resp, nil
+}
+
+// CreateOrUpdateUserSecret creates or updates a users codespace secret
+//
+// Creates or updates a secret for a user's codespace with an encrypted value. Encrypt your secret using LibSodium.
+// You must authenticate using an access token with the codespace or codespace:secrets scope to use this endpoint. User must also have Codespaces access to use this endpoint.
+// GitHub Apps must have write access to the codespaces_user_secrets user permission and codespaces_secrets repository permission on all referenced repositories to use this endpoint.
+//
+// GitHub API docs: https://docs.github.com/en/rest/codespaces/secrets?apiVersion=2022-11-28#create-or-update-a-secret-for-the-authenticated-user
+func (s *CodespacesService) CreateOrUpdateUserSecret(ctx context.Context, eSecret *EncryptedSecret) (*Response, error) {
+	u := fmt.Sprintf("user/codespaces/secrets/%v", eSecret.Name)
+	return s.createOrUpdateSecret(ctx, u, eSecret)
+}
+
+// CreateOrUpdateOrgSecret creates or updates an orgs codespace secret
+//
+// Creates or updates an organization secret with an encrypted value. Encrypt your secret using LibSodium. You must authenticate using an access token with the admin:org scope to use this endpoint.
+//
+// GitHub API docs: https://docs.github.com/en/rest/codespaces/organization-secrets?apiVersion=2022-11-28#create-or-update-an-organization-secret
+func (s *CodespacesService) CreateOrUpdateOrgSecret(ctx context.Context, org string, eSecret *EncryptedSecret) (*Response, error) {
+	u := fmt.Sprintf("orgs/%v/codespaces/secrets/%v", org, eSecret.Name)
+	return s.createOrUpdateSecret(ctx, u, eSecret)
+}
+
+// CreateOrUpdateRepoSecret creates or updates a repos codespace secret
+//
+// Creates or updates a repository secret with an encrypted value. Encrypt your secret using LibSodium. You must authenticate using an access token with the repo scope to use this endpoint. GitHub Apps must have write access to the codespaces_secrets repository permission to use this endpoint.
+//
+// GitHub API docs: https://docs.github.com/en/rest/codespaces/repository-secrets?apiVersion=2022-11-28#create-or-update-a-repository-secret
+func (s *CodespacesService) CreateOrUpdateRepoSecret(ctx context.Context, owner, repo string, eSecret *EncryptedSecret) (*Response, error) {
+	u := fmt.Sprintf("repos/%v/%v/codespaces/secrets/%v", owner, repo, eSecret.Name)
+	return s.createOrUpdateSecret(ctx, u, eSecret)
+}
+
+func (s *CodespacesService) createOrUpdateSecret(ctx context.Context, url string, eSecret *EncryptedSecret) (*Response, error) {
+	req, err := s.client.NewRequest("PUT", url, eSecret)
+	if err != nil {
+		return nil, err
+	}
+
+	resp, err := s.client.Do(ctx, req, nil)
+	if err != nil {
+		return resp, err
+	}
+
+	return resp, nil
+}
+
+// DeleteUserSecret deletes a users codespace secret
+//
+// Deletes a secret from a user's codespaces using the secret name. Deleting the secret will remove access from all codespaces that were allowed to access the secret.
+// You must authenticate using an access token with the codespace or codespace:secrets scope to use this endpoint. User must have Codespaces access to use this endpoint.
+// GitHub Apps must have write access to the codespaces_user_secrets user permission to use this endpoint.
+//
+// GitHub API docs: https://docs.github.com/en/rest/codespaces/secrets?apiVersion=2022-11-28#delete-a-secret-for-the-authenticated-user
+func (s *CodespacesService) DeleteUserSecret(ctx context.Context, name string) (*Response, error) {
+	u := fmt.Sprintf("user/codespaces/secrets/%v", name)
+	return s.deleteSecret(ctx, u)
+}
+
+// DeleteOrgSecret deletes an orgs codespace secret
+//
+// Deletes an organization secret using the secret name. You must authenticate using an access token with the admin:org scope to use this endpoint.
+//
+// GitHub API docs: https://docs.github.com/en/rest/codespaces/organization-secrets?apiVersion=2022-11-28#delete-an-organization-secret
+func (s *CodespacesService) DeleteOrgSecret(ctx context.Context, org, name string) (*Response, error) {
+	u := fmt.Sprintf("orgs/%v/codespaces/secrets/%v", org, name)
+	return s.deleteSecret(ctx, u)
+}
+
+// DeleteRepoSecret deletes a repos codespace secret
+//
+// Deletes a secret in a repository using the secret name. You must authenticate using an access token with the repo scope to use this endpoint. GitHub Apps must have write access to the codespaces_secrets repository permission to use this endpoint.
+//
+// GitHub API docs: https://docs.github.com/en/rest/codespaces/repository-secrets?apiVersion=2022-11-28#delete-a-repository-secret
+func (s *CodespacesService) DeleteRepoSecret(ctx context.Context, owner, repo, name string) (*Response, error) {
+	u := fmt.Sprintf("repos/%v/%v/codespaces/secrets/%v", owner, repo, name)
+	return s.deleteSecret(ctx, u)
+}
+
+func (s *CodespacesService) deleteSecret(ctx context.Context, url string) (*Response, error) {
+	req, err := s.client.NewRequest("DELETE", url, nil)
+	if err != nil {
+		return nil, err
+	}
+
+	resp, err := s.client.Do(ctx, req, nil)
+	if err != nil {
+		return resp, err
+	}
+
+	return resp, nil
+}
+
+// ListSelectedReposForUserSecret lists the repositories that have been granted the ability to use a user's codespace secret.
+//
+// You must authenticate using an access token with the codespace or codespace:secrets scope to use this endpoint. User must have Codespaces access to use this endpoint.
+// GitHub Apps must have read access to the codespaces_user_secrets user permission and write access to the codespaces_secrets repository permission on all referenced repositories to use this endpoint.
+//
+// GitHub API docs: https://docs.github.com/en/rest/codespaces/secrets?apiVersion=2022-11-28#list-selected-repositories-for-a-user-secret
+func (s *CodespacesService) ListSelectedReposForUserSecret(ctx context.Context, name string, opts *ListOptions) (*SelectedReposList, *Response, error) {
+	u := fmt.Sprintf("user/codespaces/secrets/%v/repositories", name)
+	u, err := addOptions(u, opts)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	return s.listSelectedReposForSecret(ctx, u)
+}
+
+// ListSelectedReposForOrgSecret lists the repositories that have been granted the ability to use an organization's codespace secret.
+//
+// Lists all repositories that have been selected when the visibility for repository access to a secret is set to selected. You must authenticate using an access token with the admin:org scope to use this endpoint.
+//
+// GitHub API docs: https://docs.github.com/en/rest/codespaces/organization-secrets?apiVersion=2022-11-28#list-selected-repositories-for-an-organization-secret
+func (s *CodespacesService) ListSelectedReposForOrgSecret(ctx context.Context, org, name string, opts *ListOptions) (*SelectedReposList, *Response, error) {
+	u := fmt.Sprintf("orgs/%v/codespaces/secrets/%v/repositories", org, name)
+	u, err := addOptions(u, opts)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	return s.listSelectedReposForSecret(ctx, u)
+}
+
+func (s *CodespacesService) listSelectedReposForSecret(ctx context.Context, url string) (*SelectedReposList, *Response, error) {
+	req, err := s.client.NewRequest("GET", url, nil)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	var repositories *SelectedReposList
+	resp, err := s.client.Do(ctx, req, &repositories)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return repositories, resp, nil
+}
+
+// SetSelectedReposForUserSecret sets the repositories that have been granted the ability to use a user's codespace secret.
+//
+// You must authenticate using an access token with the codespace or codespace:secrets scope to use this endpoint. User must have Codespaces access to use this endpoint.
+// GitHub Apps must have write access to the codespaces_user_secrets user permission and write access to the codespaces_secrets repository permission on all referenced repositories to use this endpoint.
+//
+// Github API docs: https://docs.github.com/en/rest/codespaces/secrets?apiVersion=2022-11-28#set-selected-repositories-for-a-user-secret
+func (s *CodespacesService) SetSelectedReposForUserSecret(ctx context.Context, name string, ids SelectedRepoIDs) (*Response, error) {
+	u := fmt.Sprintf("user/codespaces/secrets/%v/repositories", name)
+	return s.setSelectedRepoForSecret(ctx, u, ids)
+}
+
+// SetSelectedReposForOrgSecret sets the repositories that have been granted the ability to use a user's codespace secret.
+//
+// Replaces all repositories for an organization secret when the visibility for repository access is set to selected. The visibility is set when you Create or update an organization secret. You must authenticate using an access token with the admin:org scope to use this endpoint.
+//
+// Github API docs: https://docs.github.com/en/rest/codespaces/secrets?apiVersion=2022-11-28#set-selected-repositories-for-a-user-secret
+func (s *CodespacesService) SetSelectedReposForOrgSecret(ctx context.Context, org, name string, ids SelectedRepoIDs) (*Response, error) {
+	u := fmt.Sprintf("orgs/%v/codespaces/secrets/%v/repositories", org, name)
+	return s.setSelectedRepoForSecret(ctx, u, ids)
+}
+
+func (s *CodespacesService) setSelectedRepoForSecret(ctx context.Context, url string, ids SelectedRepoIDs) (*Response, error) {
+	type repoIDs struct {
+		SelectedIDs SelectedRepoIDs `json:"selected_repository_ids"`
+	}
+
+	req, err := s.client.NewRequest("PUT", url, repoIDs{SelectedIDs: ids})
+	if err != nil {
+		return nil, err
+	}
+
+	resp, err := s.client.Do(ctx, req, nil)
+	if err != nil {
+		return resp, err
+	}
+
+	return resp, nil
+}
+
+// AddSelectedRepoToUserSecret adds a repository to the list of repositories that have been granted the ability to use a user's codespace secret.
+//
+// Adds a repository to the selected repositories for a user's codespace secret. You must authenticate using an access token with the codespace or codespace:secrets scope to use this endpoint. User must have Codespaces access to use this endpoint. GitHub Apps must have write access to the codespaces_user_secrets user permission and write access to the codespaces_secrets repository permission on the referenced repository to use this endpoint.
+//
+// Github API docs: https://docs.github.com/en/rest/codespaces/secrets?apiVersion=2022-11-28#add-a-selected-repository-to-a-user-secret
+func (s *CodespacesService) AddSelectedRepoToUserSecret(ctx context.Context, name string, repo *Repository) (*Response, error) {
+	u := fmt.Sprintf("user/codespaces/secrets/%v/repositories/%v", name, *repo.ID)
+	return s.addSelectedRepoToSecret(ctx, u)
+}
+
+// AddSelectedRepoToOrgSecret adds a repository to the list of repositories that have been granted the ability to use an organization's codespace secret.
+//
+// Adds a repository to an organization secret when the visibility for repository access is set to selected. The visibility is set when you Create or update an organization secret. You must authenticate using an access token with the admin:org scope to use this endpoint.
+//
+// Github API docs: https://docs.github.com/en/rest/codespaces/organization-secrets?apiVersion=2022-11-28#add-selected-repository-to-an-organization-secret
+func (s *CodespacesService) AddSelectedRepoToOrgSecret(ctx context.Context, org, name string, repo *Repository) (*Response, error) {
+	u := fmt.Sprintf("orgs/%v/codespaces/secrets/%v/repositories/%v", org, name, *repo.ID)
+	return s.addSelectedRepoToSecret(ctx, u)
+}
+
+func (s *CodespacesService) addSelectedRepoToSecret(ctx context.Context, url string) (*Response, error) {
+	req, err := s.client.NewRequest("PUT", url, nil)
+	if err != nil {
+		return nil, err
+	}
+
+	resp, err := s.client.Do(ctx, req, nil)
+	if err != nil {
+		return resp, err
+	}
+
+	return resp, nil
+}
+
+// RemoveSelectedRepoFromUserSecret removes a repository from the list of repositories that have been granted the ability to use a user's codespace secret.
+//
+// Removes a repository from the selected repositories for a user's codespace secret. You must authenticate using an access token with the codespace or codespace:secrets scope to use this endpoint. User must have Codespaces access to use this endpoint. GitHub Apps must have write access to the codespaces_user_secrets user permission to use this endpoint.
+//
+// Github API docs: https://docs.github.com/en/rest/codespaces/secrets?apiVersion=2022-11-28#remove-a-selected-repository-from-a-user-secret
+func (s *CodespacesService) RemoveSelectedRepoFromUserSecret(ctx context.Context, name string, repo *Repository) (*Response, error) {
+	u := fmt.Sprintf("user/codespaces/secrets/%v/repositories/%v", name, *repo.ID)
+	return s.removeSelectedRepoFromSecret(ctx, u)
+}
+
+// RemoveSelectedRepoFromOrgSecret removes a repository from the list of repositories that have been granted the ability to use an organization's codespace secret.
+//
+// Removes a repository from an organization secret when the visibility for repository access is set to selected. The visibility is set when you Create or update an organization secret. You must authenticate using an access token with the admin:org scope to use this endpoint.
+//
+// Github API docs: https://docs.github.com/en/rest/codespaces/organization-secrets?apiVersion=2022-11-28#remove-selected-repository-from-an-organization-secret
+func (s *CodespacesService) RemoveSelectedRepoFromOrgSecret(ctx context.Context, org, name string, repo *Repository) (*Response, error) {
+	u := fmt.Sprintf("orgs/%v/codespaces/secrets/%v/repositories/%v", org, name, *repo.ID)
+	return s.removeSelectedRepoFromSecret(ctx, u)
+}
+
+func (s *CodespacesService) removeSelectedRepoFromSecret(ctx context.Context, url string) (*Response, error) {
+	req, err := s.client.NewRequest("DELETE", url, nil)
+	if err != nil {
+		return nil, err
+	}
+
+	resp, err := s.client.Do(ctx, req, nil)
+	if err != nil {
+		return resp, err
+	}
+
+	return resp, nil
+}
diff --git a/github/github-accessors.go b/github/github-accessors.go
index a9aaee81..8acb72b0 100644
--- a/github/github-accessors.go
+++ b/github/github-accessors.go
@@ -2222,6 +2222,22 @@ func (b *BranchProtectionRuleEvent) GetSender() *User {
 	return b.Sender
 }
 
+// GetActorID returns the ActorID field if it's non-nil, zero value otherwise.
+func (b *BypassActor) GetActorID() int64 {
+	if b == nil || b.ActorID == nil {
+		return 0
+	}
+	return *b.ActorID
+}
+
+// GetActorType returns the ActorType field if it's non-nil, zero value otherwise.
+func (b *BypassActor) GetActorType() string {
+	if b == nil || b.ActorType == nil {
+		return ""
+	}
+	return *b.ActorType
+}
+
 // GetApp returns the App field.
 func (c *CheckRun) GetApp() *App {
 	if c == nil {
@@ -2886,6 +2902,342 @@ func (c *CodeSearchResult) GetTotal() int {
 	return *c.Total
 }
 
+// GetBillableOwner returns the BillableOwner field.
+func (c *Codespace) GetBillableOwner() *User {
+	if c == nil {
+		return nil
+	}
+	return c.BillableOwner
+}
+
+// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise.
+func (c *Codespace) GetCreatedAt() Timestamp {
+	if c == nil || c.CreatedAt == nil {
+		return Timestamp{}
+	}
+	return *c.CreatedAt
+}
+
+// GetDevcontainerPath returns the DevcontainerPath field if it's non-nil, zero value otherwise.
+func (c *Codespace) GetDevcontainerPath() string {
+	if c == nil || c.DevcontainerPath == nil {
+		return ""
+	}
+	return *c.DevcontainerPath
+}
+
+// GetDisplayName returns the DisplayName field if it's non-nil, zero value otherwise.
+func (c *Codespace) GetDisplayName() string {
+	if c == nil || c.DisplayName == nil {
+		return ""
+	}
+	return *c.DisplayName
+}
+
+// GetEnvironmentID returns the EnvironmentID field if it's non-nil, zero value otherwise.
+func (c *Codespace) GetEnvironmentID() string {
+	if c == nil || c.EnvironmentID == nil {
+		return ""
+	}
+	return *c.EnvironmentID
+}
+
+// GetGitStatus returns the GitStatus field.
+func (c *Codespace) GetGitStatus() *CodespacesGitStatus {
+	if c == nil {
+		return nil
+	}
+	return c.GitStatus
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (c *Codespace) GetID() int64 {
+	if c == nil || c.ID == nil {
+		return 0
+	}
+	return *c.ID
+}
+
+// GetIdleTimeoutMinutes returns the IdleTimeoutMinutes field if it's non-nil, zero value otherwise.
+func (c *Codespace) GetIdleTimeoutMinutes() int {
+	if c == nil || c.IdleTimeoutMinutes == nil {
+		return 0
+	}
+	return *c.IdleTimeoutMinutes
+}
+
+// GetIdleTimeoutNotice returns the IdleTimeoutNotice field if it's non-nil, zero value otherwise.
+func (c *Codespace) GetIdleTimeoutNotice() string {
+	if c == nil || c.IdleTimeoutNotice == nil {
+		return ""
+	}
+	return *c.IdleTimeoutNotice
+}
+
+// GetLastKnownStopNotice returns the LastKnownStopNotice field if it's non-nil, zero value otherwise.
+func (c *Codespace) GetLastKnownStopNotice() string {
+	if c == nil || c.LastKnownStopNotice == nil {
+		return ""
+	}
+	return *c.LastKnownStopNotice
+}
+
+// GetLastUsedAt returns the LastUsedAt field if it's non-nil, zero value otherwise.
+func (c *Codespace) GetLastUsedAt() Timestamp {
+	if c == nil || c.LastUsedAt == nil {
+		return Timestamp{}
+	}
+	return *c.LastUsedAt
+}
+
+// GetLocation returns the Location field if it's non-nil, zero value otherwise.
+func (c *Codespace) GetLocation() string {
+	if c == nil || c.Location == nil {
+		return ""
+	}
+	return *c.Location
+}
+
+// GetMachine returns the Machine field.
+func (c *Codespace) GetMachine() *CodespacesMachine {
+	if c == nil {
+		return nil
+	}
+	return c.Machine
+}
+
+// GetMachinesURL returns the MachinesURL field if it's non-nil, zero value otherwise.
+func (c *Codespace) GetMachinesURL() string {
+	if c == nil || c.MachinesURL == nil {
+		return ""
+	}
+	return *c.MachinesURL
+}
+
+// GetName returns the Name field if it's non-nil, zero value otherwise.
+func (c *Codespace) GetName() string {
+	if c == nil || c.Name == nil {
+		return ""
+	}
+	return *c.Name
+}
+
+// GetOwner returns the Owner field.
+func (c *Codespace) GetOwner() *User {
+	if c == nil {
+		return nil
+	}
+	return c.Owner
+}
+
+// GetPendingOperation returns the PendingOperation field if it's non-nil, zero value otherwise.
+func (c *Codespace) GetPendingOperation() bool {
+	if c == nil || c.PendingOperation == nil {
+		return false
+	}
+	return *c.PendingOperation
+}
+
+// GetPendingOperationDisabledReason returns the PendingOperationDisabledReason field if it's non-nil, zero value otherwise.
+func (c *Codespace) GetPendingOperationDisabledReason() string {
+	if c == nil || c.PendingOperationDisabledReason == nil {
+		return ""
+	}
+	return *c.PendingOperationDisabledReason
+}
+
+// GetPrebuild returns the Prebuild field if it's non-nil, zero value otherwise.
+func (c *Codespace) GetPrebuild() bool {
+	if c == nil || c.Prebuild == nil {
+		return false
+	}
+	return *c.Prebuild
+}
+
+// GetPullsURL returns the PullsURL field if it's non-nil, zero value otherwise.
+func (c *Codespace) GetPullsURL() string {
+	if c == nil || c.PullsURL == nil {
+		return ""
+	}
+	return *c.PullsURL
+}
+
+// GetRepository returns the Repository field.
+func (c *Codespace) GetRepository() *Repository {
+	if c == nil {
+		return nil
+	}
+	return c.Repository
+}
+
+// GetRetentionExpiresAt returns the RetentionExpiresAt field if it's non-nil, zero value otherwise.
+func (c *Codespace) GetRetentionExpiresAt() Timestamp {
+	if c == nil || c.RetentionExpiresAt == nil {
+		return Timestamp{}
+	}
+	return *c.RetentionExpiresAt
+}
+
+// GetRetentionPeriodMinutes returns the RetentionPeriodMinutes field if it's non-nil, zero value otherwise.
+func (c *Codespace) GetRetentionPeriodMinutes() int {
+	if c == nil || c.RetentionPeriodMinutes == nil {
+		return 0
+	}
+	return *c.RetentionPeriodMinutes
+}
+
+// GetRuntimeConstraints returns the RuntimeConstraints field.
+func (c *Codespace) GetRuntimeConstraints() *CodespacesRuntimeConstraints {
+	if c == nil {
+		return nil
+	}
+	return c.RuntimeConstraints
+}
+
+// GetStartURL returns the StartURL field if it's non-nil, zero value otherwise.
+func (c *Codespace) GetStartURL() string {
+	if c == nil || c.StartURL == nil {
+		return ""
+	}
+	return *c.StartURL
+}
+
+// GetState returns the State field if it's non-nil, zero value otherwise.
+func (c *Codespace) GetState() string {
+	if c == nil || c.State == nil {
+		return ""
+	}
+	return *c.State
+}
+
+// GetStopURL returns the StopURL field if it's non-nil, zero value otherwise.
+func (c *Codespace) GetStopURL() string {
+	if c == nil || c.StopURL == nil {
+		return ""
+	}
+	return *c.StopURL
+}
+
+// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise.
+func (c *Codespace) GetUpdatedAt() Timestamp {
+	if c == nil || c.UpdatedAt == nil {
+		return Timestamp{}
+	}
+	return *c.UpdatedAt
+}
+
+// GetURL returns the URL field if it's non-nil, zero value otherwise.
+func (c *Codespace) GetURL() string {
+	if c == nil || c.URL == nil {
+		return ""
+	}
+	return *c.URL
+}
+
+// GetWebURL returns the WebURL field if it's non-nil, zero value otherwise.
+func (c *Codespace) GetWebURL() string {
+	if c == nil || c.WebURL == nil {
+		return ""
+	}
+	return *c.WebURL
+}
+
+// GetAhead returns the Ahead field if it's non-nil, zero value otherwise.
+func (c *CodespacesGitStatus) GetAhead() int {
+	if c == nil || c.Ahead == nil {
+		return 0
+	}
+	return *c.Ahead
+}
+
+// GetBehind returns the Behind field if it's non-nil, zero value otherwise.
+func (c *CodespacesGitStatus) GetBehind() int {
+	if c == nil || c.Behind == nil {
+		return 0
+	}
+	return *c.Behind
+}
+
+// GetHasUncommittedChanges returns the HasUncommittedChanges field if it's non-nil, zero value otherwise.
+func (c *CodespacesGitStatus) GetHasUncommittedChanges() bool {
+	if c == nil || c.HasUncommittedChanges == nil {
+		return false
+	}
+	return *c.HasUncommittedChanges
+}
+
+// GetHasUnpushedChanges returns the HasUnpushedChanges field if it's non-nil, zero value otherwise.
+func (c *CodespacesGitStatus) GetHasUnpushedChanges() bool {
+	if c == nil || c.HasUnpushedChanges == nil {
+		return false
+	}
+	return *c.HasUnpushedChanges
+}
+
+// GetRef returns the Ref field if it's non-nil, zero value otherwise.
+func (c *CodespacesGitStatus) GetRef() string {
+	if c == nil || c.Ref == nil {
+		return ""
+	}
+	return *c.Ref
+}
+
+// GetCPUs returns the CPUs field if it's non-nil, zero value otherwise.
+func (c *CodespacesMachine) GetCPUs() int {
+	if c == nil || c.CPUs == nil {
+		return 0
+	}
+	return *c.CPUs
+}
+
+// GetDisplayName returns the DisplayName field if it's non-nil, zero value otherwise.
+func (c *CodespacesMachine) GetDisplayName() string {
+	if c == nil || c.DisplayName == nil {
+		return ""
+	}
+	return *c.DisplayName
+}
+
+// GetMemoryInBytes returns the MemoryInBytes field if it's non-nil, zero value otherwise.
+func (c *CodespacesMachine) GetMemoryInBytes() int64 {
+	if c == nil || c.MemoryInBytes == nil {
+		return 0
+	}
+	return *c.MemoryInBytes
+}
+
+// GetName returns the Name field if it's non-nil, zero value otherwise.
+func (c *CodespacesMachine) GetName() string {
+	if c == nil || c.Name == nil {
+		return ""
+	}
+	return *c.Name
+}
+
+// GetOperatingSystem returns the OperatingSystem field if it's non-nil, zero value otherwise.
+func (c *CodespacesMachine) GetOperatingSystem() string {
+	if c == nil || c.OperatingSystem == nil {
+		return ""
+	}
+	return *c.OperatingSystem
+}
+
+// GetPrebuildAvailability returns the PrebuildAvailability field if it's non-nil, zero value otherwise.
+func (c *CodespacesMachine) GetPrebuildAvailability() string {
+	if c == nil || c.PrebuildAvailability == nil {
+		return ""
+	}
+	return *c.PrebuildAvailability
+}
+
+// GetStorageInBytes returns the StorageInBytes field if it's non-nil, zero value otherwise.
+func (c *CodespacesMachine) GetStorageInBytes() int64 {
+	if c == nil || c.StorageInBytes == nil {
+		return 0
+	}
+	return *c.StorageInBytes
+}
+
 // GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise.
 func (c *CollaboratorInvitation) GetCreatedAt() Timestamp {
 	if c == nil || c.CreatedAt == nil {
@@ -4006,6 +4358,86 @@ func (c *CreateCheckSuiteOptions) GetHeadBranch() string {
 	return *c.HeadBranch
 }
 
+// GetClientIP returns the ClientIP field if it's non-nil, zero value otherwise.
+func (c *CreateCodespaceOptions) GetClientIP() string {
+	if c == nil || c.ClientIP == nil {
+		return ""
+	}
+	return *c.ClientIP
+}
+
+// GetDevcontainerPath returns the DevcontainerPath field if it's non-nil, zero value otherwise.
+func (c *CreateCodespaceOptions) GetDevcontainerPath() string {
+	if c == nil || c.DevcontainerPath == nil {
+		return ""
+	}
+	return *c.DevcontainerPath
+}
+
+// GetDisplayName returns the DisplayName field if it's non-nil, zero value otherwise.
+func (c *CreateCodespaceOptions) GetDisplayName() string {
+	if c == nil || c.DisplayName == nil {
+		return ""
+	}
+	return *c.DisplayName
+}
+
+// GetGeo returns the Geo field if it's non-nil, zero value otherwise.
+func (c *CreateCodespaceOptions) GetGeo() string {
+	if c == nil || c.Geo == nil {
+		return ""
+	}
+	return *c.Geo
+}
+
+// GetIdleTimeoutMinutes returns the IdleTimeoutMinutes field if it's non-nil, zero value otherwise.
+func (c *CreateCodespaceOptions) GetIdleTimeoutMinutes() int {
+	if c == nil || c.IdleTimeoutMinutes == nil {
+		return 0
+	}
+	return *c.IdleTimeoutMinutes
+}
+
+// GetMachine returns the Machine field if it's non-nil, zero value otherwise.
+func (c *CreateCodespaceOptions) GetMachine() string {
+	if c == nil || c.Machine == nil {
+		return ""
+	}
+	return *c.Machine
+}
+
+// GetMultiRepoPermissionsOptOut returns the MultiRepoPermissionsOptOut field if it's non-nil, zero value otherwise.
+func (c *CreateCodespaceOptions) GetMultiRepoPermissionsOptOut() bool {
+	if c == nil || c.MultiRepoPermissionsOptOut == nil {
+		return false
+	}
+	return *c.MultiRepoPermissionsOptOut
+}
+
+// GetRef returns the Ref field if it's non-nil, zero value otherwise.
+func (c *CreateCodespaceOptions) GetRef() string {
+	if c == nil || c.Ref == nil {
+		return ""
+	}
+	return *c.Ref
+}
+
+// GetRetentionPeriodMinutes returns the RetentionPeriodMinutes field if it's non-nil, zero value otherwise.
+func (c *CreateCodespaceOptions) GetRetentionPeriodMinutes() int {
+	if c == nil || c.RetentionPeriodMinutes == nil {
+		return 0
+	}
+	return *c.RetentionPeriodMinutes
+}
+
+// GetWorkingDirectory returns the WorkingDirectory field if it's non-nil, zero value otherwise.
+func (c *CreateCodespaceOptions) GetWorkingDirectory() string {
+	if c == nil || c.WorkingDirectory == nil {
+		return ""
+	}
+	return *c.WorkingDirectory
+}
+
 // GetDescription returns the Description field if it's non-nil, zero value otherwise.
 func (c *CreateEvent) GetDescription() string {
 	if c == nil || c.Description == nil {
@@ -4262,6 +4694,30 @@ func (c *CustomRepoRoles) GetName() string {
 	return *c.Name
 }
 
+// GetQuerySuite returns the QuerySuite field if it's non-nil, zero value otherwise.
+func (d *DefaultSetupConfiguration) GetQuerySuite() string {
+	if d == nil || d.QuerySuite == nil {
+		return ""
+	}
+	return *d.QuerySuite
+}
+
+// GetState returns the State field if it's non-nil, zero value otherwise.
+func (d *DefaultSetupConfiguration) GetState() string {
+	if d == nil || d.State == nil {
+		return ""
+	}
+	return *d.State
+}
+
+// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise.
+func (d *DefaultSetupConfiguration) GetUpdatedAt() Timestamp {
+	if d == nil || d.UpdatedAt == nil {
+		return Timestamp{}
+	}
+	return *d.UpdatedAt
+}
+
 // GetInstallation returns the Installation field.
 func (d *DeleteEvent) GetInstallation() *Installation {
 	if d == nil {
@@ -6310,6 +6766,14 @@ func (f *ForkEvent) GetSender() *User {
 	return f.Sender
 }
 
+// GetWorkFolder returns the WorkFolder field if it's non-nil, zero value otherwise.
+func (g *GenerateJITConfigRequest) GetWorkFolder() string {
+	if g == nil || g.WorkFolder == nil {
+		return ""
+	}
+	return *g.WorkFolder
+}
+
 // GetPreviousTagName returns the PreviousTagName field if it's non-nil, zero value otherwise.
 func (g *GenerateNotesOptions) GetPreviousTagName() string {
 	if g == nil || g.PreviousTagName == nil {
@@ -8934,6 +9398,14 @@ func (i *IssueStats) GetTotalIssues() int {
 	return *i.TotalIssues
 }
 
+// GetEncodedJITConfig returns the EncodedJITConfig field if it's non-nil, zero value otherwise.
+func (j *JITRunnerConfig) GetEncodedJITConfig() string {
+	if j == nil || j.EncodedJITConfig == nil {
+		return ""
+	}
+	return *j.EncodedJITConfig
+}
+
 // GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise.
 func (j *Jobs) GetTotalCount() int {
 	if j == nil || j.TotalCount == nil {
@@ -9454,6 +9926,14 @@ func (l *ListCheckSuiteResults) GetTotal() int {
 	return *l.Total
 }
 
+// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise.
+func (l *ListCodespaces) GetTotalCount() int {
+	if l == nil || l.TotalCount == nil {
+		return 0
+	}
+	return *l.TotalCount
+}
+
 // GetAffiliation returns the Affiliation field if it's non-nil, zero value otherwise.
 func (l *ListCollaboratorOptions) GetAffiliation() string {
 	if l == nil || l.Affiliation == nil {
@@ -17918,6 +18398,14 @@ func (r *RepositoryRelease) GetZipballURL() string {
 	return *r.ZipballURL
 }
 
+// GetParameters returns the Parameters field if it's non-nil, zero value otherwise.
+func (r *RepositoryRule) GetParameters() json.RawMessage {
+	if r == nil || r.Parameters == nil {
+		return json.RawMessage{}
+	}
+	return *r.Parameters
+}
+
 // GetCommit returns the Commit field.
 func (r *RepositoryTag) GetCommit() *Commit {
 	if r == nil {
@@ -18366,6 +18854,118 @@ func (r *Rule) GetSeverity() string {
 	return *r.Severity
 }
 
+// GetName returns the Name field if it's non-nil, zero value otherwise.
+func (r *RulePatternParameters) GetName() string {
+	if r == nil || r.Name == nil {
+		return ""
+	}
+	return *r.Name
+}
+
+// GetNegate returns the Negate field if it's non-nil, zero value otherwise.
+func (r *RulePatternParameters) GetNegate() bool {
+	if r == nil || r.Negate == nil {
+		return false
+	}
+	return *r.Negate
+}
+
+// GetIntegrationID returns the IntegrationID field if it's non-nil, zero value otherwise.
+func (r *RuleRequiredStatusChecks) GetIntegrationID() int64 {
+	if r == nil || r.IntegrationID == nil {
+		return 0
+	}
+	return *r.IntegrationID
+}
+
+// GetBypassMode returns the BypassMode field if it's non-nil, zero value otherwise.
+func (r *Ruleset) GetBypassMode() string {
+	if r == nil || r.BypassMode == nil {
+		return ""
+	}
+	return *r.BypassMode
+}
+
+// GetConditions returns the Conditions field.
+func (r *Ruleset) GetConditions() *RulesetConditions {
+	if r == nil {
+		return nil
+	}
+	return r.Conditions
+}
+
+// GetLinks returns the Links field.
+func (r *Ruleset) GetLinks() *RulesetLinks {
+	if r == nil {
+		return nil
+	}
+	return r.Links
+}
+
+// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise.
+func (r *Ruleset) GetNodeID() string {
+	if r == nil || r.NodeID == nil {
+		return ""
+	}
+	return *r.NodeID
+}
+
+// GetSourceType returns the SourceType field if it's non-nil, zero value otherwise.
+func (r *Ruleset) GetSourceType() string {
+	if r == nil || r.SourceType == nil {
+		return ""
+	}
+	return *r.SourceType
+}
+
+// GetTarget returns the Target field if it's non-nil, zero value otherwise.
+func (r *Ruleset) GetTarget() string {
+	if r == nil || r.Target == nil {
+		return ""
+	}
+	return *r.Target
+}
+
+// GetRefName returns the RefName field.
+func (r *RulesetConditions) GetRefName() *RulesetRefConditionParameters {
+	if r == nil {
+		return nil
+	}
+	return r.RefName
+}
+
+// GetRepositoryName returns the RepositoryName field.
+func (r *RulesetConditions) GetRepositoryName() *RulesetRepositoryConditionParameters {
+	if r == nil {
+		return nil
+	}
+	return r.RepositoryName
+}
+
+// GetHRef returns the HRef field if it's non-nil, zero value otherwise.
+func (r *RulesetLink) GetHRef() string {
+	if r == nil || r.HRef == nil {
+		return ""
+	}
+	return *r.HRef
+}
+
+// GetSelf returns the Self field.
+func (r *RulesetLinks) GetSelf() *RulesetLink {
+	if r == nil {
+		return nil
+	}
+	return r.Self
+}
+
+// GetProtected returns the Protected field if it's non-nil, zero value otherwise.
+func (r *RulesetRepositoryConditionParameters) GetProtected() bool {
+	if r == nil || r.Protected == nil {
+		return false
+	}
+	return *r.Protected
+}
+
 // GetBusy returns the Busy field if it's non-nil, zero value otherwise.
 func (r *Runner) GetBusy() bool {
 	if r == nil || r.Busy == nil {
@@ -20998,6 +21598,30 @@ func (u *UpdateCheckRunOptions) GetStatus() string {
 	return *u.Status
 }
 
+// GetQuerySuite returns the QuerySuite field if it's non-nil, zero value otherwise.
+func (u *UpdateDefaultSetupConfigurationOptions) GetQuerySuite() string {
+	if u == nil || u.QuerySuite == nil {
+		return ""
+	}
+	return *u.QuerySuite
+}
+
+// GetRunID returns the RunID field if it's non-nil, zero value otherwise.
+func (u *UpdateDefaultSetupConfigurationResponse) GetRunID() int64 {
+	if u == nil || u.RunID == nil {
+		return 0
+	}
+	return *u.RunID
+}
+
+// GetRunURL returns the RunURL field if it's non-nil, zero value otherwise.
+func (u *UpdateDefaultSetupConfigurationResponse) GetRunURL() string {
+	if u == nil || u.RunURL == nil {
+		return ""
+	}
+	return *u.RunURL
+}
+
 // GetAllowsPublicRepositories returns the AllowsPublicRepositories field if it's non-nil, zero value otherwise.
 func (u *UpdateRunnerGroupRequest) GetAllowsPublicRepositories() bool {
 	if u == nil || u.AllowsPublicRepositories == nil {
diff --git a/github/github.go b/github/github.go
index 7d8aef53..2c062dc3 100644
--- a/github/github.go
+++ b/github/github.go
@@ -28,7 +28,7 @@ import (
 )
 
 const (
-	Version = "v53.0.0"
+	Version = "v53.1.0"
 
 	defaultAPIVersion = "2022-11-28"
 	defaultBaseURL    = "https://api.github.com/"
@@ -187,6 +187,7 @@ type Client struct {
 	Billing        *BillingService
 	Checks         *ChecksService
 	CodeScanning   *CodeScanningService
+	Codespaces     *CodespacesService
 	Dependabot     *DependabotService
 	Enterprise     *EnterpriseService
 	Gists          *GistsService
@@ -325,6 +326,7 @@ func NewClient(httpClient *http.Client) *Client {
 	c.Billing = (*BillingService)(&c.common)
 	c.Checks = (*ChecksService)(&c.common)
 	c.CodeScanning = (*CodeScanningService)(&c.common)
+	c.Codespaces = (*CodespacesService)(&c.common)
 	c.Dependabot = (*DependabotService)(&c.common)
 	c.Enterprise = (*EnterpriseService)(&c.common)
 	c.Gists = (*GistsService)(&c.common)
diff --git a/github/orgs_rules.go b/github/orgs_rules.go
new file mode 100644
index 00000000..a3905af8
--- /dev/null
+++ b/github/orgs_rules.go
@@ -0,0 +1,105 @@
+// Copyright 2023 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"
+)
+
+// GetAllOrganizationRulesets gets all the rulesets for the specified organization.
+//
+// GitHub API docs: https://docs.github.com/en/rest/orgs/rules#get-all-organization-repository-rulesets
+func (s *OrganizationsService) GetAllOrganizationRulesets(ctx context.Context, org string) ([]*Ruleset, *Response, error) {
+	u := fmt.Sprintf("orgs/%v/rulesets", org)
+
+	req, err := s.client.NewRequest("GET", u, nil)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	var rulesets []*Ruleset
+	resp, err := s.client.Do(ctx, req, &rulesets)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return rulesets, resp, nil
+}
+
+// CreateOrganizationRuleset creates a ruleset for the specified organization.
+//
+// GitHub API docs: https://docs.github.com/en/rest/orgs/rules#create-an-organization-repository-ruleset
+func (s *OrganizationsService) CreateOrganizationRuleset(ctx context.Context, org string, rs *Ruleset) (*Ruleset, *Response, error) {
+	u := fmt.Sprintf("orgs/%v/rulesets", org)
+
+	req, err := s.client.NewRequest("POST", u, rs)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	var ruleset *Ruleset
+	resp, err := s.client.Do(ctx, req, &ruleset)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return ruleset, resp, nil
+}
+
+// GetOrganizationRuleset gets a ruleset from the specified organization.
+//
+// GitHub API docs: https://docs.github.com/en/rest/orgs/rules#get-an-organization-repository-ruleset
+func (s *OrganizationsService) GetOrganizationRuleset(ctx context.Context, org string, rulesetID int64) (*Ruleset, *Response, error) {
+	u := fmt.Sprintf("orgs/%v/rulesets/%v", org, rulesetID)
+
+	req, err := s.client.NewRequest("GET", u, nil)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	var ruleset *Ruleset
+	resp, err := s.client.Do(ctx, req, &ruleset)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return ruleset, resp, nil
+}
+
+// UpdateOrganizationRuleset updates a ruleset from the specified organization.
+//
+// GitHub API docs: https://docs.github.com/en/rest/orgs/rules#update-an-organization-repository-ruleset
+func (s *OrganizationsService) UpdateOrganizationRuleset(ctx context.Context, org string, rulesetID int64, rs *Ruleset) (*Ruleset, *Response, error) {
+	u := fmt.Sprintf("orgs/%v/rulesets/%v", org, rulesetID)
+
+	req, err := s.client.NewRequest("PUT", u, rs)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	var ruleset *Ruleset
+	resp, err := s.client.Do(ctx, req, &ruleset)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return ruleset, resp, nil
+}
+
+// DeleteOrganizationRuleset deletes a ruleset from the specified organization.
+//
+// GitHub API docs: https://docs.github.com/en/rest/orgs/rules#delete-an-organization-repository-ruleset
+func (s *OrganizationsService) DeleteOrganizationRuleset(ctx context.Context, org string, rulesetID int64) (*Response, error) {
+	u := fmt.Sprintf("orgs/%v/rulesets/%v", org, rulesetID)
+
+	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_contents.go b/github/repos_contents.go
index be58fd52..874a3277 100644
--- a/github/repos_contents.go
+++ b/github/repos_contents.go
@@ -192,8 +192,15 @@ func (s *RepositoriesService) DownloadContentsWithMeta(ctx context.Context, owne
 // as possible, both result types will be returned but only one will contain a
 // value and the other will be nil.
 //
+// Due to an auth vulnerability issue in the GitHub v3 API, ".." is not allowed
+// to appear anywhere in the "path" or this method will return an error.
+//
 // GitHub API docs: https://docs.github.com/en/rest/repos/contents#get-repository-content
 func (s *RepositoriesService) GetContents(ctx context.Context, owner, repo, path string, opts *RepositoryContentGetOptions) (fileContent *RepositoryContent, directoryContent []*RepositoryContent, resp *Response, err error) {
+	if strings.Contains(path, "..") {
+		return nil, nil, nil, errors.New("path must not contain '..' due to auth vulnerability issue")
+	}
+
 	escapedPath := (&url.URL{Path: strings.TrimSuffix(path, "/")}).String()
 	u := fmt.Sprintf("repos/%s/%s/contents/%s", owner, repo, escapedPath)
 	u, err = addOptions(u, opts)
diff --git a/github/repos_rules.go b/github/repos_rules.go
new file mode 100644
index 00000000..64e7c9ca
--- /dev/null
+++ b/github/repos_rules.go
@@ -0,0 +1,447 @@
+// Copyright 2023 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"
+)
+
+// BypassActor represents the bypass actors from a ruleset.
+type BypassActor struct {
+	ActorID *int64 `json:"actor_id,omitempty"`
+	// Possible values for ActorType are: Team, Integration
+	ActorType *string `json:"actor_type,omitempty"`
+}
+
+// RulesetLink represents a single link object from GitHub ruleset request _links.
+type RulesetLink struct {
+	HRef *string `json:"href,omitempty"`
+}
+
+// RulesetLinks represents the "_links" object in a Ruleset.
+type RulesetLinks struct {
+	Self *RulesetLink `json:"self,omitempty"`
+}
+
+// RulesetRefConditionParameters represents the conditions object for ref_names.
+type RulesetRefConditionParameters struct {
+	Include []string `json:"include,omitempty"`
+	Exclude []string `json:"exclude,omitempty"`
+}
+
+// RulesetRepositoryConditionParameters represents the conditions object for repository_names.
+type RulesetRepositoryConditionParameters struct {
+	Include   []string `json:"include,omitempty"`
+	Exclude   []string `json:"exclude,omitempty"`
+	Protected *bool    `json:"protected,omitempty"`
+}
+
+// RulesetCondition represents the conditions object in a ruleset.
+type RulesetConditions struct {
+	RefName        *RulesetRefConditionParameters        `json:"ref_name,omitempty"`
+	RepositoryName *RulesetRepositoryConditionParameters `json:"repository_name,omitempty"`
+}
+
+// RulePatternParameters represents the rule pattern parameters.
+type RulePatternParameters struct {
+	Name *string `json:"name,omitempty"`
+	// If Negate is true, the rule will fail if the pattern matches.
+	Negate *bool `json:"negate,omitempty"`
+	// Possible values for Operator are: starts_with, ends_with, contains, regex
+	Operator string `json:"operator"`
+	Pattern  string `json:"pattern"`
+}
+
+// UpdateAllowsFetchAndMergeRuleParameters represents the update rule parameters.
+type UpdateAllowsFetchAndMergeRuleParameters struct {
+	UpdateAllowsFetchAndMerge bool `json:"update_allows_fetch_and_merge"`
+}
+
+// RequiredDeploymentEnvironmentsRuleParameters represents the required_deployments rule parameters.
+type RequiredDeploymentEnvironmentsRuleParameters struct {
+	RequiredDeploymentEnvironments []string `json:"required_deployment_environments"`
+}
+
+// PullRequestRuleParameters represents the pull_request rule parameters.
+type PullRequestRuleParameters struct {
+	DismissStaleReviewsOnPush      bool `json:"dismiss_stale_reviews_on_push"`
+	RequireCodeOwnerReview         bool `json:"require_code_owner_review"`
+	RequireLastPushApproval        bool `json:"require_last_push_approval"`
+	RequiredApprovingReviewCount   int  `json:"required_approving_review_count"`
+	RequiredReviewThreadResolution bool `json:"required_review_thread_resolution"`
+}
+
+// RuleRequiredStatusChecks represents the RequiredStatusChecks for the RequiredStatusChecksRuleParameters object.
+type RuleRequiredStatusChecks struct {
+	Context       string `json:"context"`
+	IntegrationID *int64 `json:"integration_id,omitempty"`
+}
+
+// RequiredStatusChecksRuleParameters represents the required_status_checks rule parameters.
+type RequiredStatusChecksRuleParameters struct {
+	RequiredStatusChecks             []RuleRequiredStatusChecks `json:"required_status_checks"`
+	StrictRequiredStatusChecksPolicy bool                       `json:"strict_required_status_checks_policy"`
+}
+
+// RepositoryRule represents a GitHub Rule.
+type RepositoryRule struct {
+	Type       string           `json:"type"`
+	Parameters *json.RawMessage `json:"parameters,omitempty"`
+}
+
+// UnmarshalJSON implements the json.Unmarshaler interface.
+// This helps us handle the fact that RepositoryRule parameter field can be of numerous types.
+func (r *RepositoryRule) UnmarshalJSON(data []byte) error {
+	type rule RepositoryRule
+	var RepositoryRule rule
+	if err := json.Unmarshal(data, &RepositoryRule); err != nil {
+		return err
+	}
+
+	r.Type = RepositoryRule.Type
+
+	switch RepositoryRule.Type {
+	case "creation", "deletion", "required_linear_history", "required_signatures", "non_fast_forward":
+		r.Parameters = nil
+	case "update":
+		params := UpdateAllowsFetchAndMergeRuleParameters{}
+		if err := json.Unmarshal(*RepositoryRule.Parameters, &params); err != nil {
+			return err
+		}
+
+		bytes, _ := json.Marshal(params)
+		rawParams := json.RawMessage(bytes)
+
+		r.Parameters = &rawParams
+	case "required_deployments":
+		params := RequiredDeploymentEnvironmentsRuleParameters{}
+		if err := json.Unmarshal(*RepositoryRule.Parameters, &params); err != nil {
+			return err
+		}
+
+		bytes, _ := json.Marshal(params)
+		rawParams := json.RawMessage(bytes)
+
+		r.Parameters = &rawParams
+	case "commit_message_pattern", "commit_author_email_pattern", "committer_email_pattern", "branch_name_pattern", "tag_name_pattern":
+		params := RulePatternParameters{}
+		if err := json.Unmarshal(*RepositoryRule.Parameters, &params); err != nil {
+			return err
+		}
+
+		bytes, _ := json.Marshal(params)
+		rawParams := json.RawMessage(bytes)
+
+		r.Parameters = &rawParams
+	case "pull_request":
+		params := PullRequestRuleParameters{}
+		if err := json.Unmarshal(*RepositoryRule.Parameters, &params); err != nil {
+			return err
+		}
+
+		bytes, _ := json.Marshal(params)
+		rawParams := json.RawMessage(bytes)
+
+		r.Parameters = &rawParams
+	case "required_status_checks":
+		params := RequiredStatusChecksRuleParameters{}
+		if err := json.Unmarshal(*RepositoryRule.Parameters, &params); err != nil {
+			return err
+		}
+
+		bytes, _ := json.Marshal(params)
+		rawParams := json.RawMessage(bytes)
+
+		r.Parameters = &rawParams
+	default:
+		r.Type = ""
+		r.Parameters = nil
+		return fmt.Errorf("RepositoryRule.Type %T is not yet implemented, unable to unmarshal", RepositoryRule.Type)
+	}
+
+	return nil
+}
+
+// NewCreationRule creates a rule to only allow users with bypass permission to create matching refs.
+func NewCreationRule() (rule *RepositoryRule) {
+	return &RepositoryRule{
+		Type: "creation",
+	}
+}
+
+// NewUpdateRule creates a rule to only allow users with bypass permission to update matching refs.
+func NewUpdateRule(params *UpdateAllowsFetchAndMergeRuleParameters) (rule *RepositoryRule) {
+	bytes, _ := json.Marshal(params)
+
+	rawParams := json.RawMessage(bytes)
+
+	return &RepositoryRule{
+		Type:       "update",
+		Parameters: &rawParams,
+	}
+}
+
+// NewDeletionRule creates a rule to only allow users with bypass permissions to delete matching refs.
+func NewDeletionRule() (rule *RepositoryRule) {
+	return &RepositoryRule{
+		Type: "deletion",
+	}
+}
+
+// NewRequiredLinearHistoryRule creates a rule to prevent merge commits from being pushed to matching branches.
+func NewRequiredLinearHistoryRule() (rule *RepositoryRule) {
+	return &RepositoryRule{
+		Type: "required_linear_history",
+	}
+}
+
+// NewRequiredDeploymentsRule creates a rule to require environments to be successfully deployed before they can be merged into the matching branches.
+func NewRequiredDeploymentsRule(params *RequiredDeploymentEnvironmentsRuleParameters) (rule *RepositoryRule) {
+	bytes, _ := json.Marshal(params)
+
+	rawParams := json.RawMessage(bytes)
+
+	return &RepositoryRule{
+		Type:       "required_deployments",
+		Parameters: &rawParams,
+	}
+}
+
+// NewRequiredSignaturesRule creates a rule a to require commits pushed to matching branches to have verified signatures.
+func NewRequiredSignaturesRule() (rule *RepositoryRule) {
+	return &RepositoryRule{
+		Type: "required_signatures",
+	}
+}
+
+// NewPullRequestRule creates a rule to require all commits be made to a non-target branch and submitted via a pull request before they can be merged.
+func NewPullRequestRule(params *PullRequestRuleParameters) (rule *RepositoryRule) {
+	bytes, _ := json.Marshal(params)
+
+	rawParams := json.RawMessage(bytes)
+
+	return &RepositoryRule{
+		Type:       "pull_request",
+		Parameters: &rawParams,
+	}
+}
+
+// NewRequiredStatusChecksRule creates a rule to require which status checks must pass before branches can be merged into a branch rule.
+func NewRequiredStatusChecksRule(params *RequiredStatusChecksRuleParameters) (rule *RepositoryRule) {
+	bytes, _ := json.Marshal(params)
+
+	rawParams := json.RawMessage(bytes)
+
+	return &RepositoryRule{
+		Type:       "required_status_checks",
+		Parameters: &rawParams,
+	}
+}
+
+// NewNonFastForwardRule creates a rule as part to prevent users with push access from force pushing to matching branches.
+func NewNonFastForwardRule() (rule *RepositoryRule) {
+	return &RepositoryRule{
+		Type: "non_fast_forward",
+	}
+}
+
+// NewCommitMessagePatternRule creates a rule to restrict commit message patterns being pushed to matching branches.
+func NewCommitMessagePatternRule(params *RulePatternParameters) (rule *RepositoryRule) {
+	bytes, _ := json.Marshal(params)
+
+	rawParams := json.RawMessage(bytes)
+
+	return &RepositoryRule{
+		Type:       "commit_message_pattern",
+		Parameters: &rawParams,
+	}
+}
+
+// NewCommitAuthorEmailPatternRule creates a rule to restrict commits with author email patterns being merged into matching branches.
+func NewCommitAuthorEmailPatternRule(params *RulePatternParameters) (rule *RepositoryRule) {
+	bytes, _ := json.Marshal(params)
+
+	rawParams := json.RawMessage(bytes)
+
+	return &RepositoryRule{
+		Type:       "commit_author_email_pattern",
+		Parameters: &rawParams,
+	}
+}
+
+// NewCommitterEmailPatternRule creates a rule to restrict commits with committer email patterns being merged into matching branches.
+func NewCommitterEmailPatternRule(params *RulePatternParameters) (rule *RepositoryRule) {
+	bytes, _ := json.Marshal(params)
+
+	rawParams := json.RawMessage(bytes)
+
+	return &RepositoryRule{
+		Type:       "committer_email_pattern",
+		Parameters: &rawParams,
+	}
+}
+
+// NewBranchNamePatternRule creates a rule to restrict branch patterns from being merged into matching branches.
+func NewBranchNamePatternRule(params *RulePatternParameters) (rule *RepositoryRule) {
+	bytes, _ := json.Marshal(params)
+
+	rawParams := json.RawMessage(bytes)
+
+	return &RepositoryRule{
+		Type:       "branch_name_pattern",
+		Parameters: &rawParams,
+	}
+}
+
+// NewTagNamePatternRule creates a rule to restrict tag patterns contained in non-target branches from being merged into matching branches.
+func NewTagNamePatternRule(params *RulePatternParameters) (rule *RepositoryRule) {
+	bytes, _ := json.Marshal(params)
+
+	rawParams := json.RawMessage(bytes)
+
+	return &RepositoryRule{
+		Type:       "tag_name_pattern",
+		Parameters: &rawParams,
+	}
+}
+
+// Ruleset represents a GitHub ruleset object.
+type Ruleset struct {
+	ID   int64  `json:"id"`
+	Name string `json:"name"`
+	// Possible values for Target are branch, tag
+	Target *string `json:"target,omitempty"`
+	// Possible values for SourceType are: Repository, Organization
+	SourceType *string `json:"source_type,omitempty"`
+	Source     string  `json:"source"`
+	// Possible values for Enforcement are: disabled, active, evaluate
+	Enforcement string `json:"enforcement"`
+	// Possible values for BypassMode are: none, repository, organization
+	BypassMode   *string            `json:"bypass_mode,omitempty"`
+	BypassActors []*BypassActor     `json:"bypass_actors,omitempty"`
+	NodeID       *string            `json:"node_id,omitempty"`
+	Links        *RulesetLinks      `json:"_links,omitempty"`
+	Conditions   *RulesetConditions `json:"conditions,omitempty"`
+	Rules        []*RepositoryRule  `json:"rules,omitempty"`
+}
+
+// GetRulesForBranch gets all the rules that apply to the specified branch.
+//
+// GitHub API docs: https://docs.github.com/en/rest/repos/rules#get-rules-for-a-branch
+func (s *RepositoriesService) GetRulesForBranch(ctx context.Context, owner, repo, branch string) ([]*RepositoryRule, *Response, error) {
+	u := fmt.Sprintf("repos/%v/%v/rules/branches/%v", owner, repo, branch)
+
+	req, err := s.client.NewRequest("GET", u, nil)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	var rules []*RepositoryRule
+	resp, err := s.client.Do(ctx, req, &rules)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return rules, resp, nil
+}
+
+// GetAllRulesets gets all the rules that apply to the specified repository.
+// If includesParents is true, rulesets configured at the organization level that apply to the repository will be returned.
+//
+// GitHub API docs: https://docs.github.com/en/rest/repos/rules#get-all-repository-rulesets
+func (s *RepositoriesService) GetAllRulesets(ctx context.Context, owner, repo string, includesParents bool) ([]*Ruleset, *Response, error) {
+	u := fmt.Sprintf("repos/%v/%v/rulesets?includes_parents=%v", owner, repo, includesParents)
+
+	req, err := s.client.NewRequest("GET", u, nil)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	var ruleset []*Ruleset
+	resp, err := s.client.Do(ctx, req, &ruleset)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return ruleset, resp, nil
+}
+
+// CreateRuleset creates a ruleset for the specified repository.
+//
+// GitHub API docs: https://docs.github.com/en/rest/repos/rules#create-a-repository-ruleset
+func (s *RepositoriesService) CreateRuleset(ctx context.Context, owner, repo string, rs *Ruleset) (*Ruleset, *Response, error) {
+	u := fmt.Sprintf("repos/%v/%v/rulesets", owner, repo)
+
+	req, err := s.client.NewRequest("POST", u, rs)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	var ruleset *Ruleset
+	resp, err := s.client.Do(ctx, req, &ruleset)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return ruleset, resp, nil
+}
+
+// GetRuleset gets a ruleset for the specified repository.
+// If includesParents is true, rulesets configured at the organization level that apply to the repository will be returned.
+//
+// GitHub API docs: https://docs.github.com/en/rest/repos/rules#get-a-repository-ruleset
+func (s *RepositoriesService) GetRuleset(ctx context.Context, owner, repo string, rulesetID int64, includesParents bool) (*Ruleset, *Response, error) {
+	u := fmt.Sprintf("repos/%v/%v/rulesets/%v?includes_parents=%v", owner, repo, rulesetID, includesParents)
+
+	req, err := s.client.NewRequest("GET", u, nil)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	var ruleset *Ruleset
+	resp, err := s.client.Do(ctx, req, &ruleset)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return ruleset, resp, nil
+}
+
+// UpdateRuleset updates a ruleset for the specified repository.
+//
+// GitHub API docs: https://docs.github.com/en/rest/repos/rules#update-a-repository-ruleset
+func (s *RepositoriesService) UpdateRuleset(ctx context.Context, owner, repo string, rulesetID int64, rs *Ruleset) (*Ruleset, *Response, error) {
+	u := fmt.Sprintf("repos/%v/%v/rulesets/%v", owner, repo, rulesetID)
+
+	req, err := s.client.NewRequest("PUT", u, rs)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	var ruleset *Ruleset
+	resp, err := s.client.Do(ctx, req, &ruleset)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return ruleset, resp, nil
+}
+
+// DeleteRuleset deletes a ruleset for the specified repository.
+//
+// GitHub API docs: https://docs.github.com/en/rest/repos/rules#delete-a-repository-ruleset
+func (s *RepositoriesService) DeleteRuleset(ctx context.Context, owner, repo string, rulesetID int64) (*Response, error) {
+	u := fmt.Sprintf("repos/%v/%v/rulesets/%v", owner, repo, rulesetID)
+
+	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/actions_runners_test.go b/github/actions_runners_test.go
index 9b338641..8063152f 100644
--- a/github/actions_runners_test.go
+++ b/github/actions_runners_test.go
@@ -7,6 +7,7 @@ package github
 
 import (
 	"context"
+	"encoding/json"
 	"fmt"
 	"net/http"
 	"testing"
@@ -56,6 +57,94 @@ func TestActionsService_ListRunnerApplicationDownloads(t *testing.T) {
 	})
 }
 
+func TestActionsService_GenerateOrgJITConfig(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	input := &GenerateJITConfigRequest{Name: "test", RunnerGroupID: 1, Labels: []string{"one", "two"}}
+
+	mux.HandleFunc("/orgs/o/actions/runners/generate-jitconfig", func(w http.ResponseWriter, r *http.Request) {
+		v := new(GenerateJITConfigRequest)
+		json.NewDecoder(r.Body).Decode(v)
+
+		testMethod(t, r, "POST")
+		if !cmp.Equal(v, input) {
+			t.Errorf("Request body = %+v, want %+v", v, input)
+		}
+
+		fmt.Fprint(w, `{"encoded_jit_config":"foo"}`)
+	})
+
+	ctx := context.Background()
+	jitConfig, _, err := client.Actions.GenerateOrgJITConfig(ctx, "o", input)
+	if err != nil {
+		t.Errorf("Actions.GenerateOrgJITConfig returned error: %v", err)
+	}
+
+	want := &JITRunnerConfig{EncodedJITConfig: String("foo")}
+	if !cmp.Equal(jitConfig, want) {
+		t.Errorf("Actions.GenerateOrgJITConfig returned %+v, want %+v", jitConfig, want)
+	}
+
+	const methodName = "GenerateOrgJITConfig"
+	testBadOptions(t, methodName, func() (err error) {
+		_, _, err = client.Actions.GenerateOrgJITConfig(ctx, "\n", input)
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		got, resp, err := client.Actions.GenerateOrgJITConfig(ctx, "o", input)
+		if got != nil {
+			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+		}
+		return resp, err
+	})
+}
+
+func TestActionsService_GenerateRepoJITConfig(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	input := &GenerateJITConfigRequest{Name: "test", RunnerGroupID: 1, Labels: []string{"one", "two"}}
+
+	mux.HandleFunc("/repos/o/r/actions/runners/generate-jitconfig", func(w http.ResponseWriter, r *http.Request) {
+		v := new(GenerateJITConfigRequest)
+		json.NewDecoder(r.Body).Decode(v)
+
+		testMethod(t, r, "POST")
+		if !cmp.Equal(v, input) {
+			t.Errorf("Request body = %+v, want %+v", v, input)
+		}
+
+		fmt.Fprint(w, `{"encoded_jit_config":"foo"}`)
+	})
+
+	ctx := context.Background()
+	jitConfig, _, err := client.Actions.GenerateRepoJITConfig(ctx, "o", "r", input)
+	if err != nil {
+		t.Errorf("Actions.GenerateRepoJITConfig returned error: %v", err)
+	}
+
+	want := &JITRunnerConfig{EncodedJITConfig: String("foo")}
+	if !cmp.Equal(jitConfig, want) {
+		t.Errorf("Actions.GenerateRepoJITConfig returned %+v, want %+v", jitConfig, want)
+	}
+
+	const methodName = "GenerateRepoJITConfig"
+	testBadOptions(t, methodName, func() (err error) {
+		_, _, err = client.Actions.GenerateRepoJITConfig(ctx, "\n", "\n", input)
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		got, resp, err := client.Actions.GenerateRepoJITConfig(ctx, "o", "r", input)
+		if got != nil {
+			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+		}
+		return resp, err
+	})
+}
+
 func TestActionsService_CreateRegistrationToken(t *testing.T) {
 	client, mux, _, teardown := setup()
 	defer teardown()
diff --git a/github/code-scanning_test.go b/github/code-scanning_test.go
index 7911fca6..29c0b617 100644
--- a/github/code-scanning_test.go
+++ b/github/code-scanning_test.go
@@ -1177,3 +1177,105 @@ func TestCodeScanningService_GetAnalysis(t *testing.T) {
 		return resp, err
 	})
 }
+
+func TestCodeScanningService_GetDefaultSetupConfiguration(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/repos/o/r/code-scanning/default-setup", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "GET")
+		_, err := fmt.Fprint(w, `{
+		"state": "configured",
+		"languages": [
+			"javascript",
+			"javascript-typescript",
+			"typescript"
+		],
+		"query_suite": "default",
+		"updated_at": "2006-01-02T15:04:05Z"
+		}`)
+		if err != nil {
+			t.Fatal(err)
+		}
+	})
+
+	ctx := context.Background()
+	cfg, _, err := client.CodeScanning.GetDefaultSetupConfiguration(ctx, "o", "r")
+	if err != nil {
+		t.Errorf("CodeScanning.GetDefaultSetupConfiguration returned error: %v", err)
+	}
+
+	date := &Timestamp{time.Date(2006, time.January, 02, 15, 04, 05, 0, time.UTC)}
+	want := &DefaultSetupConfiguration{
+		State:      String("configured"),
+		Languages:  []string{"javascript", "javascript-typescript", "typescript"},
+		QuerySuite: String("default"),
+		UpdatedAt:  date,
+	}
+	if !cmp.Equal(cfg, want) {
+		t.Errorf("CodeScanning.GetDefaultSetupConfiguration returned %+v, want %+v", cfg, want)
+	}
+
+	const methodName = "GetDefaultSetupConfiguration"
+	testBadOptions(t, methodName, func() (err error) {
+		_, _, err = client.CodeScanning.GetDefaultSetupConfiguration(ctx, "\n", "\n")
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		got, resp, err := client.CodeScanning.GetDefaultSetupConfiguration(ctx, "o", "r")
+		if got != nil {
+			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+		}
+		return resp, err
+	})
+}
+
+func TestCodeScanningService_UpdateDefaultSetupConfiguration(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/repos/o/r/code-scanning/default-setup", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "PATCH")
+		_, err := fmt.Fprint(w, `{
+		"run_id": 5301214200,
+		"run_url": "https://api.github.com/repos/o/r/actions/runs/5301214200"
+		}`)
+		if err != nil {
+			t.Fatal(err)
+		}
+	})
+
+	ctx := context.Background()
+	options := &UpdateDefaultSetupConfigurationOptions{
+		State:      "configured",
+		Languages:  []string{"go"},
+		QuerySuite: String("default"),
+	}
+	got, _, err := client.CodeScanning.UpdateDefaultSetupConfiguration(ctx, "o", "r", options)
+	if err != nil {
+		t.Errorf("CodeScanning.UpdateDefaultSetupConfiguration returned error: %v", err)
+	}
+
+	want := &UpdateDefaultSetupConfigurationResponse{
+		RunID:  Int64(5301214200),
+		RunURL: String("https://api.github.com/repos/o/r/actions/runs/5301214200"),
+	}
+	if !cmp.Equal(got, want) {
+		t.Errorf("CodeScanning.UpdateDefaultSetupConfiguration returned %+v, want %+v", got, want)
+	}
+
+	const methodName = "UpdateDefaultSetupConfiguration"
+	testBadOptions(t, methodName, func() (err error) {
+		_, _, err = client.CodeScanning.UpdateDefaultSetupConfiguration(ctx, "\n", "\n", nil)
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		got, resp, err := client.CodeScanning.UpdateDefaultSetupConfiguration(ctx, "o", "r", nil)
+		if got != nil {
+			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+		}
+		return resp, err
+	})
+}
diff --git a/github/codespaces_secrets_test.go b/github/codespaces_secrets_test.go
new file mode 100644
index 00000000..33c0ad99
--- /dev/null
+++ b/github/codespaces_secrets_test.go
@@ -0,0 +1,803 @@
+// Copyright 2023 The go-github AUTHORS. All rights reserved.
+//
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package github
+
+import (
+	"context"
+	"fmt"
+	"net/http"
+	"testing"
+	"time"
+
+	"github.com/google/go-cmp/cmp"
+)
+
+func TestCodespacesService_ListSecrets(t *testing.T) {
+	type test struct {
+		name       string
+		handleFunc func(*http.ServeMux)
+		call       func(context.Context, *Client) (*Secrets, *Response, error)
+		badCall    func(context.Context, *Client) (*Secrets, *Response, error)
+		methodName string
+	}
+	opts := &ListOptions{Page: 2, PerPage: 2}
+	tests := []test{
+		{
+			name: "User",
+			handleFunc: func(mux *http.ServeMux) {
+				mux.HandleFunc("/user/codespaces/secrets", func(w http.ResponseWriter, r *http.Request) {
+					testMethod(t, r, "GET")
+					testFormValues(t, r, values{"per_page": "2", "page": "2"})
+					fmt.Fprint(w, `{"total_count":4,"secrets":[{"name":"A","created_at":"2019-01-02T15:04:05Z","updated_at":"2020-01-02T15:04:05Z"},{"name":"B","created_at":"2019-01-02T15:04:05Z","updated_at":"2020-01-02T15:04:05Z"}]}`)
+				})
+			},
+			call: func(ctx context.Context, client *Client) (*Secrets, *Response, error) {
+				return client.Codespaces.ListUserSecrets(ctx, opts)
+			},
+			methodName: "ListUserSecrets",
+		},
+		{
+			name: "Org",
+			handleFunc: func(mux *http.ServeMux) {
+				mux.HandleFunc("/orgs/o/codespaces/secrets", func(w http.ResponseWriter, r *http.Request) {
+					testMethod(t, r, "GET")
+					testFormValues(t, r, values{"per_page": "2", "page": "2"})
+					fmt.Fprint(w, `{"total_count":4,"secrets":[{"name":"A","created_at":"2019-01-02T15:04:05Z","updated_at":"2020-01-02T15:04:05Z"},{"name":"B","created_at":"2019-01-02T15:04:05Z","updated_at":"2020-01-02T15:04:05Z"}]}`)
+				})
+			},
+			call: func(ctx context.Context, client *Client) (*Secrets, *Response, error) {
+				return client.Codespaces.ListOrgSecrets(ctx, "o", opts)
+			},
+			badCall: func(ctx context.Context, client *Client) (*Secrets, *Response, error) {
+				return client.Codespaces.ListOrgSecrets(ctx, "\n", opts)
+			},
+			methodName: "ListOrgSecrets",
+		},
+		{
+			name: "Repo",
+			handleFunc: func(mux *http.ServeMux) {
+				mux.HandleFunc("/repos/o/r/codespaces/secrets", func(w http.ResponseWriter, r *http.Request) {
+					testMethod(t, r, "GET")
+					testFormValues(t, r, values{"per_page": "2", "page": "2"})
+					fmt.Fprint(w, `{"total_count":4,"secrets":[{"name":"A","created_at":"2019-01-02T15:04:05Z","updated_at":"2020-01-02T15:04:05Z"},{"name":"B","created_at":"2019-01-02T15:04:05Z","updated_at":"2020-01-02T15:04:05Z"}]}`)
+				})
+			},
+			call: func(ctx context.Context, client *Client) (*Secrets, *Response, error) {
+				return client.Codespaces.ListRepoSecrets(ctx, "o", "r", opts)
+			},
+			badCall: func(ctx context.Context, client *Client) (*Secrets, *Response, error) {
+				return client.Codespaces.ListRepoSecrets(ctx, "\n", "\n", opts)
+			},
+			methodName: "ListRepoSecrets",
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			client, mux, _, teardown := setup()
+			defer teardown()
+
+			tt.handleFunc(mux)
+
+			ctx := context.Background()
+			secrets, _, err := tt.call(ctx, client)
+			if err != nil {
+				t.Errorf("Codespaces.%v returned error: %v", tt.methodName, err)
+			}
+
+			want := &Secrets{
+				TotalCount: 4,
+				Secrets: []*Secret{
+					{Name: "A", CreatedAt: Timestamp{time.Date(2019, time.January, 02, 15, 04, 05, 0, time.UTC)}, UpdatedAt: Timestamp{time.Date(2020, time.January, 02, 15, 04, 05, 0, time.UTC)}},
+					{Name: "B", CreatedAt: Timestamp{time.Date(2019, time.January, 02, 15, 04, 05, 0, time.UTC)}, UpdatedAt: Timestamp{time.Date(2020, time.January, 02, 15, 04, 05, 0, time.UTC)}},
+				},
+			}
+			if !cmp.Equal(secrets, want) {
+				t.Errorf("Codespaces.%v returned %+v, want %+v", tt.methodName, secrets, want)
+			}
+
+			if tt.badCall != nil {
+				testBadOptions(t, tt.methodName, func() (err error) {
+					_, _, err = tt.badCall(ctx, client)
+					return err
+				})
+			}
+
+			testNewRequestAndDoFailure(t, tt.methodName, client, func() (*Response, error) {
+				got, resp, err := tt.call(ctx, client)
+				if got != nil {
+					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", tt.methodName, got)
+				}
+				return resp, err
+			})
+		})
+	}
+}
+
+func TestCodespacesService_GetSecret(t *testing.T) {
+	type test struct {
+		name       string
+		handleFunc func(*http.ServeMux)
+		call       func(context.Context, *Client) (*Secret, *Response, error)
+		badCall    func(context.Context, *Client) (*Secret, *Response, error)
+		methodName string
+	}
+	tests := []test{
+		{
+			name: "User",
+			handleFunc: func(mux *http.ServeMux) {
+				mux.HandleFunc("/user/codespaces/secrets/NAME", func(w http.ResponseWriter, r *http.Request) {
+					testMethod(t, r, "GET")
+					fmt.Fprint(w, `{"name":"A","created_at":"2019-01-02T15:04:05Z","updated_at":"2020-01-02T15:04:05Z"}`)
+				})
+			},
+			call: func(ctx context.Context, client *Client) (*Secret, *Response, error) {
+				return client.Codespaces.GetUserSecret(ctx, "NAME")
+			},
+			methodName: "GetUserSecret",
+		},
+		{
+			name: "Org",
+			handleFunc: func(mux *http.ServeMux) {
+				mux.HandleFunc("/orgs/o/codespaces/secrets/NAME", func(w http.ResponseWriter, r *http.Request) {
+					testMethod(t, r, "GET")
+					fmt.Fprint(w, `{"name":"A","created_at":"2019-01-02T15:04:05Z","updated_at":"2020-01-02T15:04:05Z"}`)
+				})
+			},
+			call: func(ctx context.Context, client *Client) (*Secret, *Response, error) {
+				return client.Codespaces.GetOrgSecret(ctx, "o", "NAME")
+			},
+			badCall: func(ctx context.Context, client *Client) (*Secret, *Response, error) {
+				return client.Codespaces.GetOrgSecret(ctx, "\n", "\n")
+			},
+			methodName: "GetOrgSecret",
+		},
+		{
+			name: "Repo",
+			handleFunc: func(mux *http.ServeMux) {
+				mux.HandleFunc("/repos/o/r/codespaces/secrets/NAME", func(w http.ResponseWriter, r *http.Request) {
+					testMethod(t, r, "GET")
+					fmt.Fprint(w, `{"name":"A","created_at":"2019-01-02T15:04:05Z","updated_at":"2020-01-02T15:04:05Z"}`)
+				})
+			},
+			call: func(ctx context.Context, client *Client) (*Secret, *Response, error) {
+				return client.Codespaces.GetRepoSecret(ctx, "o", "r", "NAME")
+			},
+			badCall: func(ctx context.Context, client *Client) (*Secret, *Response, error) {
+				return client.Codespaces.GetRepoSecret(ctx, "\n", "\n", "\n")
+			},
+			methodName: "GetRepoSecret",
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			client, mux, _, teardown := setup()
+			defer teardown()
+
+			tt.handleFunc(mux)
+
+			ctx := context.Background()
+			secret, _, err := tt.call(ctx, client)
+			if err != nil {
+				t.Errorf("Codespaces.%v returned error: %v", tt.methodName, err)
+			}
+
+			want := &Secret{Name: "A", CreatedAt: Timestamp{time.Date(2019, time.January, 02, 15, 04, 05, 0, time.UTC)}, UpdatedAt: Timestamp{time.Date(2020, time.January, 02, 15, 04, 05, 0, time.UTC)}}
+			if !cmp.Equal(secret, want) {
+				t.Errorf("Codespaces.%v returned %+v, want %+v", tt.methodName, secret, want)
+			}
+
+			if tt.badCall != nil {
+				testBadOptions(t, tt.methodName, func() (err error) {
+					_, _, err = tt.badCall(ctx, client)
+					return err
+				})
+			}
+
+			testNewRequestAndDoFailure(t, tt.methodName, client, func() (*Response, error) {
+				got, resp, err := tt.call(ctx, client)
+				if got != nil {
+					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", tt.methodName, got)
+				}
+				return resp, err
+			})
+		})
+	}
+}
+
+func TestCodespacesService_CreateOrUpdateSecret(t *testing.T) {
+	type test struct {
+		name       string
+		handleFunc func(*http.ServeMux)
+		call       func(context.Context, *Client, *EncryptedSecret) (*Response, error)
+		badCall    func(context.Context, *Client, *EncryptedSecret) (*Response, error)
+		methodName string
+	}
+	tests := []test{
+		{
+			name: "User",
+			handleFunc: func(mux *http.ServeMux) {
+				mux.HandleFunc("/user/codespaces/secrets/NAME", func(w http.ResponseWriter, r *http.Request) {
+					testMethod(t, r, "PUT")
+					testHeader(t, r, "Content-Type", "application/json")
+					testBody(t, r, `{"key_id":"1234","encrypted_value":"QIv="}`+"\n")
+					w.WriteHeader(http.StatusCreated)
+				})
+			},
+			call: func(ctx context.Context, client *Client, e *EncryptedSecret) (*Response, error) {
+				return client.Codespaces.CreateOrUpdateUserSecret(ctx, e)
+			},
+			methodName: "CreateOrUpdateUserSecret",
+		},
+		{
+			name: "Org",
+			handleFunc: func(mux *http.ServeMux) {
+				mux.HandleFunc("/orgs/o/codespaces/secrets/NAME", func(w http.ResponseWriter, r *http.Request) {
+					testMethod(t, r, "PUT")
+					testHeader(t, r, "Content-Type", "application/json")
+					testBody(t, r, `{"key_id":"1234","encrypted_value":"QIv="}`+"\n")
+					w.WriteHeader(http.StatusCreated)
+				})
+			},
+			call: func(ctx context.Context, client *Client, e *EncryptedSecret) (*Response, error) {
+				return client.Codespaces.CreateOrUpdateOrgSecret(ctx, "o", e)
+			},
+			badCall: func(ctx context.Context, client *Client, e *EncryptedSecret) (*Response, error) {
+				return client.Codespaces.CreateOrUpdateOrgSecret(ctx, "\n", e)
+			},
+			methodName: "CreateOrUpdateOrgSecret",
+		},
+		{
+			name: "Repo",
+			handleFunc: func(mux *http.ServeMux) {
+				mux.HandleFunc("/repos/o/r/codespaces/secrets/NAME", func(w http.ResponseWriter, r *http.Request) {
+					testMethod(t, r, "PUT")
+					testHeader(t, r, "Content-Type", "application/json")
+					testBody(t, r, `{"key_id":"1234","encrypted_value":"QIv="}`+"\n")
+					w.WriteHeader(http.StatusCreated)
+				})
+			},
+			call: func(ctx context.Context, client *Client, e *EncryptedSecret) (*Response, error) {
+				return client.Codespaces.CreateOrUpdateRepoSecret(ctx, "o", "r", e)
+			},
+			badCall: func(ctx context.Context, client *Client, e *EncryptedSecret) (*Response, error) {
+				return client.Codespaces.CreateOrUpdateRepoSecret(ctx, "\n", "\n", e)
+			},
+			methodName: "CreateOrUpdateRepoSecret",
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			client, mux, _, teardown := setup()
+			defer teardown()
+
+			tt.handleFunc(mux)
+
+			input := &EncryptedSecret{
+				Name:           "NAME",
+				EncryptedValue: "QIv=",
+				KeyID:          "1234",
+			}
+			ctx := context.Background()
+			_, err := tt.call(ctx, client, input)
+			if err != nil {
+				t.Errorf("Codespaces.%v returned error: %v", tt.methodName, err)
+			}
+
+			if tt.badCall != nil {
+				testBadOptions(t, tt.methodName, func() (err error) {
+					_, err = tt.badCall(ctx, client, input)
+					return err
+				})
+			}
+
+			testNewRequestAndDoFailure(t, tt.methodName, client, func() (*Response, error) {
+				return tt.call(ctx, client, input)
+			})
+		})
+	}
+}
+
+func TestCodespacesService_DeleteSecret(t *testing.T) {
+	type test struct {
+		name       string
+		handleFunc func(*http.ServeMux)
+		call       func(context.Context, *Client) (*Response, error)
+		badCall    func(context.Context, *Client) (*Response, error)
+		methodName string
+	}
+	tests := []test{
+		{
+			name: "User",
+			handleFunc: func(mux *http.ServeMux) {
+				mux.HandleFunc("/user/codespaces/secrets/NAME", func(w http.ResponseWriter, r *http.Request) {
+					testMethod(t, r, "DELETE")
+				})
+			},
+			call: func(ctx context.Context, client *Client) (*Response, error) {
+				return client.Codespaces.DeleteUserSecret(ctx, "NAME")
+			},
+			methodName: "DeleteUserSecret",
+		},
+		{
+			name: "Org",
+			handleFunc: func(mux *http.ServeMux) {
+				mux.HandleFunc("/orgs/o/codespaces/secrets/NAME", func(w http.ResponseWriter, r *http.Request) {
+					testMethod(t, r, "DELETE")
+				})
+			},
+			call: func(ctx context.Context, client *Client) (*Response, error) {
+				return client.Codespaces.DeleteOrgSecret(ctx, "o", "NAME")
+			},
+			badCall: func(ctx context.Context, client *Client) (*Response, error) {
+				return client.Codespaces.DeleteOrgSecret(ctx, "\n", "\n")
+			},
+			methodName: "DeleteOrgSecret",
+		},
+		{
+			name: "Repo",
+			handleFunc: func(mux *http.ServeMux) {
+				mux.HandleFunc("/repos/o/r/codespaces/secrets/NAME", func(w http.ResponseWriter, r *http.Request) {
+					testMethod(t, r, "DELETE")
+				})
+			},
+			call: func(ctx context.Context, client *Client) (*Response, error) {
+				return client.Codespaces.DeleteRepoSecret(ctx, "o", "r", "NAME")
+			},
+			badCall: func(ctx context.Context, client *Client) (*Response, error) {
+				return client.Codespaces.DeleteRepoSecret(ctx, "\n", "\n", "\n")
+			},
+			methodName: "DeleteRepoSecret",
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			client, mux, _, teardown := setup()
+			defer teardown()
+
+			tt.handleFunc(mux)
+
+			ctx := context.Background()
+			_, err := tt.call(ctx, client)
+			if err != nil {
+				t.Errorf("Codespaces.%v returned error: %v", tt.methodName, err)
+			}
+
+			if tt.badCall != nil {
+				testBadOptions(t, tt.methodName, func() (err error) {
+					_, err = tt.badCall(ctx, client)
+					return err
+				})
+			}
+
+			testNewRequestAndDoFailure(t, tt.methodName, client, func() (*Response, error) {
+				return tt.call(ctx, client)
+			})
+		})
+	}
+}
+
+func TestCodespacesService_GetPublicKey(t *testing.T) {
+	type test struct {
+		name       string
+		handleFunc func(*http.ServeMux)
+		call       func(context.Context, *Client) (*PublicKey, *Response, error)
+		badCall    func(context.Context, *Client) (*PublicKey, *Response, error)
+		methodName string
+	}
+
+	tests := []test{
+		{
+			name: "User",
+			handleFunc: func(mux *http.ServeMux) {
+				mux.HandleFunc("/user/codespaces/secrets/public-key", func(w http.ResponseWriter, r *http.Request) {
+					testMethod(t, r, "GET")
+					fmt.Fprint(w, `{"key_id":"1234","key":"2Sg8iYjAxxmI2LvUXpJjkYrMxURPc8r+dB7TJyvv1234"}`)
+				})
+			},
+			call: func(ctx context.Context, client *Client) (*PublicKey, *Response, error) {
+				return client.Codespaces.GetUserPublicKey(ctx)
+			},
+			methodName: "GetUserPublicKey",
+		},
+		{
+			name: "Org",
+			handleFunc: func(mux *http.ServeMux) {
+				mux.HandleFunc("/orgs/o/codespaces/secrets/public-key", func(w http.ResponseWriter, r *http.Request) {
+					testMethod(t, r, "GET")
+					fmt.Fprint(w, `{"key_id":"1234","key":"2Sg8iYjAxxmI2LvUXpJjkYrMxURPc8r+dB7TJyvv1234"}`)
+				})
+			},
+			call: func(ctx context.Context, client *Client) (*PublicKey, *Response, error) {
+				return client.Codespaces.GetOrgPublicKey(ctx, "o")
+			},
+			badCall: func(ctx context.Context, client *Client) (*PublicKey, *Response, error) {
+				return client.Codespaces.GetOrgPublicKey(ctx, "\n")
+			},
+			methodName: "GetOrgPublicKey",
+		},
+		{
+			name: "Repo",
+			handleFunc: func(mux *http.ServeMux) {
+				mux.HandleFunc("/repos/o/r/codespaces/secrets/public-key", func(w http.ResponseWriter, r *http.Request) {
+					testMethod(t, r, "GET")
+					fmt.Fprint(w, `{"key_id":"1234","key":"2Sg8iYjAxxmI2LvUXpJjkYrMxURPc8r+dB7TJyvv1234"}`)
+				})
+			},
+			call: func(ctx context.Context, client *Client) (*PublicKey, *Response, error) {
+				return client.Codespaces.GetRepoPublicKey(ctx, "o", "r")
+			},
+			badCall: func(ctx context.Context, client *Client) (*PublicKey, *Response, error) {
+				return client.Codespaces.GetRepoPublicKey(ctx, "\n", "\n")
+			},
+			methodName: "GetRepoPublicKey",
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			client, mux, _, teardown := setup()
+			defer teardown()
+
+			tt.handleFunc(mux)
+
+			ctx := context.Background()
+			key, _, err := tt.call(ctx, client)
+			if err != nil {
+				t.Errorf("Codespaces.%v returned error: %v", tt.methodName, err)
+			}
+
+			want := &PublicKey{KeyID: String("1234"), Key: String("2Sg8iYjAxxmI2LvUXpJjkYrMxURPc8r+dB7TJyvv1234")}
+			if !cmp.Equal(key, want) {
+				t.Errorf("Codespaces.%v returned %+v, want %+v", tt.methodName, key, want)
+			}
+
+			if tt.badCall != nil {
+				testBadOptions(t, tt.methodName, func() (err error) {
+					_, _, err = tt.badCall(ctx, client)
+					return err
+				})
+			}
+
+			testNewRequestAndDoFailure(t, tt.methodName, client, func() (*Response, error) {
+				got, resp, err := tt.call(ctx, client)
+				if got != nil {
+					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", tt.methodName, got)
+				}
+				return resp, err
+			})
+		})
+	}
+}
+
+func TestCodespacesService_ListSelectedReposForSecret(t *testing.T) {
+	type test struct {
+		name       string
+		handleFunc func(*http.ServeMux)
+		call       func(context.Context, *Client) (*SelectedReposList, *Response, error)
+		badCall    func(context.Context, *Client) (*SelectedReposList, *Response, error)
+		methodName string
+	}
+	opts := &ListOptions{Page: 2, PerPage: 2}
+	tests := []test{
+		{
+			name: "User",
+			handleFunc: func(mux *http.ServeMux) {
+				mux.HandleFunc("/user/codespaces/secrets/NAME/repositories", func(w http.ResponseWriter, r *http.Request) {
+					testMethod(t, r, "GET")
+					fmt.Fprintf(w, `{"total_count":1,"repositories":[{"id":1}]}`)
+				})
+			},
+			call: func(ctx context.Context, client *Client) (*SelectedReposList, *Response, error) {
+				return client.Codespaces.ListSelectedReposForUserSecret(ctx, "NAME", opts)
+			},
+			methodName: "ListSelectedReposForUserSecret",
+		},
+		{
+			name: "Org",
+			handleFunc: func(mux *http.ServeMux) {
+				mux.HandleFunc("/orgs/o/codespaces/secrets/NAME/repositories", func(w http.ResponseWriter, r *http.Request) {
+					testMethod(t, r, "GET")
+					fmt.Fprintf(w, `{"total_count":1,"repositories":[{"id":1}]}`)
+				})
+			},
+			call: func(ctx context.Context, client *Client) (*SelectedReposList, *Response, error) {
+				return client.Codespaces.ListSelectedReposForOrgSecret(ctx, "o", "NAME", opts)
+			},
+			badCall: func(ctx context.Context, client *Client) (*SelectedReposList, *Response, error) {
+				return client.Codespaces.ListSelectedReposForOrgSecret(ctx, "\n", "\n", opts)
+			},
+			methodName: "ListSelectedReposForOrgSecret",
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			client, mux, _, teardown := setup()
+			defer teardown()
+
+			tt.handleFunc(mux)
+
+			ctx := context.Background()
+			repos, _, err := tt.call(ctx, client)
+			if err != nil {
+				t.Errorf("Codespaces.%v returned error: %v", tt.methodName, err)
+			}
+
+			want := &SelectedReposList{
+				TotalCount: Int(1),
+				Repositories: []*Repository{
+					{ID: Int64(1)},
+				},
+			}
+
+			if !cmp.Equal(repos, want) {
+				t.Errorf("Codespaces.%v returned %+v, want %+v", tt.methodName, repos, want)
+			}
+
+			if tt.badCall != nil {
+				testBadOptions(t, tt.methodName, func() (err error) {
+					_, _, err = tt.badCall(ctx, client)
+					return err
+				})
+			}
+
+			testNewRequestAndDoFailure(t, tt.methodName, client, func() (*Response, error) {
+				got, resp, err := tt.call(ctx, client)
+				if got != nil {
+					t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", tt.methodName, got)
+				}
+				return resp, err
+			})
+		})
+	}
+}
+
+func TestCodespacesService_SetSelectedReposForSecret(t *testing.T) {
+	type test struct {
+		name       string
+		handleFunc func(*http.ServeMux)
+		call       func(context.Context, *Client) (*Response, error)
+		badCall    func(context.Context, *Client) (*Response, error)
+		methodName string
+	}
+	ids := SelectedRepoIDs{64780797}
+	tests := []test{
+		{
+			name: "User",
+			handleFunc: func(mux *http.ServeMux) {
+				mux.HandleFunc("/user/codespaces/secrets/NAME/repositories", func(w http.ResponseWriter, r *http.Request) {
+					testMethod(t, r, "PUT")
+					testHeader(t, r, "Content-Type", "application/json")
+					testBody(t, r, `{"selected_repository_ids":[64780797]}`+"\n")
+				})
+			},
+			call: func(ctx context.Context, client *Client) (*Response, error) {
+				return client.Codespaces.SetSelectedReposForUserSecret(ctx, "NAME", ids)
+			},
+			methodName: "SetSelectedReposForUserSecret",
+		},
+		{
+			name: "Org",
+			handleFunc: func(mux *http.ServeMux) {
+				mux.HandleFunc("/orgs/o/codespaces/secrets/NAME/repositories", func(w http.ResponseWriter, r *http.Request) {
+					testMethod(t, r, "PUT")
+					testHeader(t, r, "Content-Type", "application/json")
+					testBody(t, r, `{"selected_repository_ids":[64780797]}`+"\n")
+				})
+			},
+			call: func(ctx context.Context, client *Client) (*Response, error) {
+				return client.Codespaces.SetSelectedReposForOrgSecret(ctx, "o", "NAME", ids)
+			},
+			badCall: func(ctx context.Context, client *Client) (*Response, error) {
+				return client.Codespaces.SetSelectedReposForOrgSecret(ctx, "\n", "\n", ids)
+			},
+			methodName: "SetSelectedReposForOrgSecret",
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			client, mux, _, teardown := setup()
+			defer teardown()
+
+			tt.handleFunc(mux)
+
+			ctx := context.Background()
+			_, err := tt.call(ctx, client)
+			if err != nil {
+				t.Errorf("Codespaces.%v returned error: %v", tt.methodName, err)
+			}
+
+			if tt.badCall != nil {
+				testBadOptions(t, tt.methodName, func() (err error) {
+					_, err = tt.badCall(ctx, client)
+					return err
+				})
+			}
+
+			testNewRequestAndDoFailure(t, tt.methodName, client, func() (*Response, error) {
+				return tt.call(ctx, client)
+			})
+		})
+	}
+}
+
+func TestCodespacesService_AddSelectedReposForSecret(t *testing.T) {
+	type test struct {
+		name       string
+		handleFunc func(*http.ServeMux)
+		call       func(context.Context, *Client) (*Response, error)
+		badCall    func(context.Context, *Client) (*Response, error)
+		methodName string
+	}
+	repo := &Repository{ID: Int64(1234)}
+	tests := []test{
+		{
+			name: "User",
+			handleFunc: func(mux *http.ServeMux) {
+				mux.HandleFunc("/user/codespaces/secrets/NAME/repositories/1234", func(w http.ResponseWriter, r *http.Request) {
+					testMethod(t, r, "PUT")
+				})
+			},
+			call: func(ctx context.Context, client *Client) (*Response, error) {
+				return client.Codespaces.AddSelectedRepoToUserSecret(ctx, "NAME", repo)
+			},
+			methodName: "AddSelectedRepoToUserSecret",
+		},
+		{
+			name: "Org",
+			handleFunc: func(mux *http.ServeMux) {
+				mux.HandleFunc("/orgs/o/codespaces/secrets/NAME/repositories/1234", func(w http.ResponseWriter, r *http.Request) {
+					testMethod(t, r, "PUT")
+				})
+			},
+			call: func(ctx context.Context, client *Client) (*Response, error) {
+				return client.Codespaces.AddSelectedRepoToOrgSecret(ctx, "o", "NAME", repo)
+			},
+			badCall: func(ctx context.Context, client *Client) (*Response, error) {
+				return client.Codespaces.AddSelectedRepoToOrgSecret(ctx, "\n", "\n", repo)
+			},
+			methodName: "AddSelectedRepoToOrgSecret",
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			client, mux, _, teardown := setup()
+			defer teardown()
+
+			tt.handleFunc(mux)
+
+			ctx := context.Background()
+			_, err := tt.call(ctx, client)
+			if err != nil {
+				t.Errorf("Codespaces.%v returned error: %v", tt.methodName, err)
+			}
+
+			if tt.badCall != nil {
+				testBadOptions(t, tt.methodName, func() (err error) {
+					_, err = tt.badCall(ctx, client)
+					return err
+				})
+			}
+
+			testNewRequestAndDoFailure(t, tt.methodName, client, func() (*Response, error) {
+				return tt.call(ctx, client)
+			})
+		})
+	}
+}
+
+func TestCodespacesService_RemoveSelectedReposFromSecret(t *testing.T) {
+	type test struct {
+		name       string
+		handleFunc func(*http.ServeMux)
+		call       func(context.Context, *Client) (*Response, error)
+		badCall    func(context.Context, *Client) (*Response, error)
+		methodName string
+	}
+	repo := &Repository{ID: Int64(1234)}
+	tests := []test{
+		{
+			name: "User",
+			handleFunc: func(mux *http.ServeMux) {
+				mux.HandleFunc("/user/codespaces/secrets/NAME/repositories/1234", func(w http.ResponseWriter, r *http.Request) {
+					testMethod(t, r, "DELETE")
+				})
+			},
+			call: func(ctx context.Context, client *Client) (*Response, error) {
+				return client.Codespaces.RemoveSelectedRepoFromUserSecret(ctx, "NAME", repo)
+			},
+			methodName: "RemoveSelectedRepoFromUserSecret",
+		},
+		{
+			name: "Org",
+			handleFunc: func(mux *http.ServeMux) {
+				mux.HandleFunc("/orgs/o/codespaces/secrets/NAME/repositories/1234", func(w http.ResponseWriter, r *http.Request) {
+					testMethod(t, r, "DELETE")
+				})
+			},
+			call: func(ctx context.Context, client *Client) (*Response, error) {
+				return client.Codespaces.RemoveSelectedRepoFromOrgSecret(ctx, "o", "NAME", repo)
+			},
+			badCall: func(ctx context.Context, client *Client) (*Response, error) {
+				return client.Codespaces.RemoveSelectedRepoFromOrgSecret(ctx, "\n", "\n", repo)
+			},
+			methodName: "RemoveSelectedRepoFromOrgSecret",
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			client, mux, _, teardown := setup()
+			defer teardown()
+
+			tt.handleFunc(mux)
+
+			ctx := context.Background()
+			_, err := tt.call(ctx, client)
+			if err != nil {
+				t.Errorf("Codespaces.%v returned error: %v", tt.methodName, err)
+			}
+
+			if tt.badCall != nil {
+				testBadOptions(t, tt.methodName, func() (err error) {
+					_, err = tt.badCall(ctx, client)
+					return err
+				})
+			}
+
+			testNewRequestAndDoFailure(t, tt.methodName, client, func() (*Response, error) {
+				return tt.call(ctx, client)
+			})
+		})
+	}
+}
+
+// func TestActionsService_ListSelectedReposForOrgSecret(t *testing.T) {
+// 	client, mux, _, teardown := setup()
+// 	defer teardown()
+
+// 	mux.HandleFunc("/orgs/o/actions/secrets/NAME/repositories", func(w http.ResponseWriter, r *http.Request) {
+// 		testMethod(t, r, "GET")
+// 		fmt.Fprintf(w, `{"total_count":1,"repositories":[{"id":1}]}`)
+// 	})
+
+// 	opts := &ListOptions{Page: 2, PerPage: 2}
+// 	ctx := context.Background()
+// 	repos, _, err := client.Actions.ListSelectedReposForOrgSecret(ctx, "o", "NAME", opts)
+// 	if err != nil {
+// 		t.Errorf("Actions.ListSelectedReposForOrgSecret returned error: %v", err)
+// 	}
+
+// 	want := &SelectedReposList{
+// 		TotalCount: Int(1),
+// 		Repositories: []*Repository{
+// 			{ID: Int64(1)},
+// 		},
+// 	}
+// 	if !cmp.Equal(repos, want) {
+// 		t.Errorf("Actions.ListSelectedReposForOrgSecret returned %+v, want %+v", repos, want)
+// 	}
+
+// 	const methodName = "ListSelectedReposForOrgSecret"
+// 	testBadOptions(t, methodName, func() (err error) {
+// 		_, _, err = client.Actions.ListSelectedReposForOrgSecret(ctx, "\n", "\n", opts)
+// 		return err
+// 	})
+
+// 	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+// 		got, resp, err := client.Actions.ListSelectedReposForOrgSecret(ctx, "o", "NAME", opts)
+// 		if got != nil {
+// 			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+// 		}
+// 		return resp, err
+// 	})
+// }
diff --git a/github/codespaces_test.go b/github/codespaces_test.go
new file mode 100644
index 00000000..8b75731b
--- /dev/null
+++ b/github/codespaces_test.go
@@ -0,0 +1,291 @@
+// Copyright 2023 The go-github AUTHORS. All rights reserved.
+//
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package github
+
+import (
+	"context"
+	"fmt"
+	"net/http"
+	"testing"
+	"time"
+
+	"github.com/google/go-cmp/cmp"
+)
+
+func TestCodespacesService_ListInRepo(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/repos/owner/repo/codespaces", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "GET")
+		testFormValues(t, r, values{
+			"page":     "1",
+			"per_page": "2",
+		})
+		fmt.Fprint(w, `{"total_count":2,"codespaces":[{"id":1,"name":"monalisa-octocat-hello-world-g4wpq6h95q","environment_id":"26a7c758-7299-4a73-b978-5a92a7ae98a0","owner":{"login":"octocat"},"billable_owner":{"login":"octocat"},"repository":{"id":1296269},"machine":{"name":"standardLinux","display_name":"4 cores, 8 GB RAM, 64 GB storage","operating_system":"linux","storage_in_bytes":68719476736,"memory_in_bytes":8589934592,"cpus":4},"prebuild":false,"devcontainer_path":".devcontainer/devcontainer.json","created_at":"2021-10-14T00:53:30-06:00","updated_at":"2021-10-14T00:53:32-06:00","last_used_at":"2021-10-14T00:53:30-06:00","state":"Available","url":"https://api.github.com/user/codespaces/monalisa-octocat-hello-world-g4wpq6h95q","git_status":{"ahead":0,"behind":0,"has_unpushed_changes":false,"has_uncommitted_changes":false,"ref":"main"},"location":"WestUs2","idle_timeout_minutes":60,"web_url":"https://monalisa-octocat-hello-world-g4wpq6h95q.github.dev","machines_url":"https://api.github.com/user/codespaces/monalisa-octocat-hello-world-g4wpq6h95q/machines","start_url":"https://api.github.com/user/codespaces/monalisa-octocat-hello-world-g4wpq6h95q/start","stop_url":"https://api.github.com/user/codespaces/monalisa-octocat-hello-world-g4wpq6h95q/stop","recent_folders":["testfolder1","testfolder2"]},{"id":2}]}`)
+	})
+
+	opt := &ListOptions{Page: 1, PerPage: 2}
+	ctx := context.Background()
+	codespaces, _, err := client.Codespaces.ListInRepo(ctx, "owner", "repo", opt)
+	if err != nil {
+		t.Errorf("Codespaces.ListInRepo returned error: %v", err)
+	}
+
+	want := &ListCodespaces{TotalCount: Int(2), Codespaces: []*Codespace{
+		{
+			ID:            Int64(1),
+			Name:          String("monalisa-octocat-hello-world-g4wpq6h95q"),
+			EnvironmentID: String("26a7c758-7299-4a73-b978-5a92a7ae98a0"),
+			Owner: &User{
+				Login: String("octocat"),
+			},
+			BillableOwner: &User{
+				Login: String("octocat"),
+			},
+			Repository: &Repository{
+				ID: Int64(1296269),
+			},
+			Machine: &CodespacesMachine{
+				Name:            String("standardLinux"),
+				DisplayName:     String("4 cores, 8 GB RAM, 64 GB storage"),
+				OperatingSystem: String("linux"),
+				StorageInBytes:  Int64(68719476736),
+				MemoryInBytes:   Int64(8589934592),
+				CPUs:            Int(4),
+			},
+			Prebuild:         Bool(false),
+			DevcontainerPath: String(".devcontainer/devcontainer.json"),
+			CreatedAt:        &Timestamp{time.Date(2021, 10, 14, 0, 53, 30, 0, time.FixedZone("", -6*60*60))},
+			UpdatedAt:        &Timestamp{time.Date(2021, 10, 14, 0, 53, 32, 0, time.FixedZone("", -6*60*60))},
+			LastUsedAt:       &Timestamp{time.Date(2021, 10, 14, 0, 53, 30, 0, time.FixedZone("", -6*60*60))},
+			State:            String("Available"),
+			URL:              String("https://api.github.com/user/codespaces/monalisa-octocat-hello-world-g4wpq6h95q"),
+			GitStatus: &CodespacesGitStatus{
+				Ahead:                 Int(0),
+				Behind:                Int(0),
+				HasUnpushedChanges:    Bool(false),
+				HasUncommittedChanges: Bool(false),
+				Ref:                   String("main"),
+			},
+			Location:           String("WestUs2"),
+			IdleTimeoutMinutes: Int(60),
+			WebURL:             String("https://monalisa-octocat-hello-world-g4wpq6h95q.github.dev"),
+			MachinesURL:        String("https://api.github.com/user/codespaces/monalisa-octocat-hello-world-g4wpq6h95q/machines"),
+			StartURL:           String("https://api.github.com/user/codespaces/monalisa-octocat-hello-world-g4wpq6h95q/start"),
+			StopURL:            String("https://api.github.com/user/codespaces/monalisa-octocat-hello-world-g4wpq6h95q/stop"),
+			RecentFolders: []string{
+				"testfolder1",
+				"testfolder2",
+			},
+		},
+		{
+			ID: Int64(2),
+		},
+	}}
+	if !cmp.Equal(codespaces, want) {
+		t.Errorf("Codespaces.ListInRepo returned %+v, want %+v", codespaces, want)
+	}
+
+	const methodName = "ListInRepo"
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		got, resp, err := client.Codespaces.ListInRepo(ctx, "", "", nil)
+		if got != nil {
+			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+		}
+		return resp, err
+	})
+}
+
+func TestCodespacesService_List(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/user/codespaces", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "GET")
+		testFormValues(t, r, values{
+			"page":          "1",
+			"per_page":      "2",
+			"repository_id": "1296269",
+		})
+		fmt.Fprint(w, `{"total_count":1,"codespaces":[{"id":1, "repository": {"id": 1296269}}]}`)
+	})
+
+	opt := &ListCodespacesOptions{ListOptions: ListOptions{Page: 1, PerPage: 2}, RepositoryID: 1296269}
+	ctx := context.Background()
+	codespaces, _, err := client.Codespaces.List(ctx, opt)
+	if err != nil {
+		t.Errorf("Codespaces.List returned error: %v", err)
+	}
+
+	want := &ListCodespaces{TotalCount: Int(1), Codespaces: []*Codespace{
+		{
+			ID: Int64(1),
+			Repository: &Repository{
+				ID: Int64(1296269),
+			},
+		},
+	}}
+	if !cmp.Equal(codespaces, want) {
+		t.Errorf("Codespaces.ListInRepo returned %+v, want %+v", codespaces, want)
+	}
+
+	const methodName = "List"
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		got, resp, err := client.Codespaces.List(ctx, nil)
+		if got != nil {
+			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+		}
+		return resp, err
+	})
+}
+
+func TestCodespacesService_CreateInRepo(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+	mux.HandleFunc("/repos/owner/repo/codespaces", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "POST")
+		testHeader(t, r, "Content-Type", "application/json")
+		testBody(t, r, `{"ref":"main","geo":"WestUs2","machine":"standardLinux","idle_timeout_minutes":60}`+"\n")
+		fmt.Fprint(w, `{"id":1, "repository": {"id": 1296269}}`)
+	})
+	input := &CreateCodespaceOptions{
+		Ref:                String("main"),
+		Geo:                String("WestUs2"),
+		Machine:            String("standardLinux"),
+		IdleTimeoutMinutes: Int(60),
+	}
+	ctx := context.Background()
+	codespace, _, err := client.Codespaces.CreateInRepo(ctx, "owner", "repo", input)
+	if err != nil {
+		t.Errorf("Codespaces.CreateInRepo returned error: %v", err)
+	}
+	want := &Codespace{
+		ID: Int64(1),
+		Repository: &Repository{
+			ID: Int64(1296269),
+		},
+	}
+
+	if !cmp.Equal(codespace, want) {
+		t.Errorf("Codespaces.CreateInRepo returned %+v, want %+v", codespace, want)
+	}
+
+	const methodName = "CreateInRepo"
+	testBadOptions(t, methodName, func() (err error) {
+		_, _, err = client.Codespaces.CreateInRepo(ctx, "\n", "", input)
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		got, resp, err := client.Codespaces.CreateInRepo(ctx, "o", "r", input)
+		if got != nil {
+			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+		}
+		return resp, err
+	})
+}
+
+func TestCodespacesService_Start(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+	mux.HandleFunc("/user/codespaces/codespace_1/start", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "POST")
+		fmt.Fprint(w, `{"id":1, "repository": {"id": 1296269}}`)
+	})
+	ctx := context.Background()
+	codespace, _, err := client.Codespaces.Start(ctx, "codespace_1")
+	if err != nil {
+		t.Errorf("Codespaces.Start returned error: %v", err)
+	}
+	want := &Codespace{
+		ID: Int64(1),
+		Repository: &Repository{
+			ID: Int64(1296269),
+		},
+	}
+
+	if !cmp.Equal(codespace, want) {
+		t.Errorf("Codespaces.Start returned %+v, want %+v", codespace, want)
+	}
+
+	const methodName = "Start"
+	testBadOptions(t, methodName, func() (err error) {
+		_, _, err = client.Codespaces.Start(ctx, "\n")
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		got, resp, err := client.Codespaces.Start(ctx, "o")
+		if got != nil {
+			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+		}
+		return resp, err
+	})
+}
+
+func TestCodespacesService_Stop(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+	mux.HandleFunc("/user/codespaces/codespace_1/stop", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "POST")
+		fmt.Fprint(w, `{"id":1, "repository": {"id": 1296269}}`)
+	})
+	ctx := context.Background()
+	codespace, _, err := client.Codespaces.Stop(ctx, "codespace_1")
+	if err != nil {
+		t.Errorf("Codespaces.Stop returned error: %v", err)
+	}
+	want := &Codespace{
+		ID: Int64(1),
+		Repository: &Repository{
+			ID: Int64(1296269),
+		},
+	}
+
+	if !cmp.Equal(codespace, want) {
+		t.Errorf("Codespaces.Stop returned %+v, want %+v", codespace, want)
+	}
+
+	const methodName = "Stop"
+	testBadOptions(t, methodName, func() (err error) {
+		_, _, err = client.Codespaces.Stop(ctx, "\n")
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		got, resp, err := client.Codespaces.Stop(ctx, "o")
+		if got != nil {
+			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+		}
+		return resp, err
+	})
+}
+
+func TestCodespacesService_Delete(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/user/codespaces/codespace_1", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "DELETE")
+	})
+
+	ctx := context.Background()
+	_, err := client.Codespaces.Delete(ctx, "codespace_1")
+	if err != nil {
+		t.Errorf("Codespaces.Delete return error: %v", err)
+	}
+
+	const methodName = "Delete"
+	testBadOptions(t, methodName, func() (err error) {
+		_, err = client.Codespaces.Delete(ctx, "\n")
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		return client.Codespaces.Delete(ctx, "codespace_1")
+	})
+}
diff --git a/github/github-accessors_test.go b/github/github-accessors_test.go
index a29baa0f..3f39d9c1 100644
--- a/github/github-accessors_test.go
+++ b/github/github-accessors_test.go
@@ -2664,6 +2664,26 @@ func TestBranchProtectionRuleEvent_GetSender(tt *testing.T) {
 	b.GetSender()
 }
 
+func TestBypassActor_GetActorID(tt *testing.T) {
+	var zeroValue int64
+	b := &BypassActor{ActorID: &zeroValue}
+	b.GetActorID()
+	b = &BypassActor{}
+	b.GetActorID()
+	b = nil
+	b.GetActorID()
+}
+
+func TestBypassActor_GetActorType(tt *testing.T) {
+	var zeroValue string
+	b := &BypassActor{ActorType: &zeroValue}
+	b.GetActorType()
+	b = &BypassActor{}
+	b.GetActorType()
+	b = nil
+	b.GetActorType()
+}
+
 func TestCheckRun_GetApp(tt *testing.T) {
 	c := &CheckRun{}
 	c.GetApp()
@@ -3419,6 +3439,408 @@ func TestCodeSearchResult_GetTotal(tt *testing.T) {
 	c.GetTotal()
 }
 
+func TestCodespace_GetBillableOwner(tt *testing.T) {
+	c := &Codespace{}
+	c.GetBillableOwner()
+	c = nil
+	c.GetBillableOwner()
+}
+
+func TestCodespace_GetCreatedAt(tt *testing.T) {
+	var zeroValue Timestamp
+	c := &Codespace{CreatedAt: &zeroValue}
+	c.GetCreatedAt()
+	c = &Codespace{}
+	c.GetCreatedAt()
+	c = nil
+	c.GetCreatedAt()
+}
+
+func TestCodespace_GetDevcontainerPath(tt *testing.T) {
+	var zeroValue string
+	c := &Codespace{DevcontainerPath: &zeroValue}
+	c.GetDevcontainerPath()
+	c = &Codespace{}
+	c.GetDevcontainerPath()
+	c = nil
+	c.GetDevcontainerPath()
+}
+
+func TestCodespace_GetDisplayName(tt *testing.T) {
+	var zeroValue string
+	c := &Codespace{DisplayName: &zeroValue}
+	c.GetDisplayName()
+	c = &Codespace{}
+	c.GetDisplayName()
+	c = nil
+	c.GetDisplayName()
+}
+
+func TestCodespace_GetEnvironmentID(tt *testing.T) {
+	var zeroValue string
+	c := &Codespace{EnvironmentID: &zeroValue}
+	c.GetEnvironmentID()
+	c = &Codespace{}
+	c.GetEnvironmentID()
+	c = nil
+	c.GetEnvironmentID()
+}
+
+func TestCodespace_GetGitStatus(tt *testing.T) {
+	c := &Codespace{}
+	c.GetGitStatus()
+	c = nil
+	c.GetGitStatus()
+}
+
+func TestCodespace_GetID(tt *testing.T) {
+	var zeroValue int64
+	c := &Codespace{ID: &zeroValue}
+	c.GetID()
+	c = &Codespace{}
+	c.GetID()
+	c = nil
+	c.GetID()
+}
+
+func TestCodespace_GetIdleTimeoutMinutes(tt *testing.T) {
+	var zeroValue int
+	c := &Codespace{IdleTimeoutMinutes: &zeroValue}
+	c.GetIdleTimeoutMinutes()
+	c = &Codespace{}
+	c.GetIdleTimeoutMinutes()
+	c = nil
+	c.GetIdleTimeoutMinutes()
+}
+
+func TestCodespace_GetIdleTimeoutNotice(tt *testing.T) {
+	var zeroValue string
+	c := &Codespace{IdleTimeoutNotice: &zeroValue}
+	c.GetIdleTimeoutNotice()
+	c = &Codespace{}
+	c.GetIdleTimeoutNotice()
+	c = nil
+	c.GetIdleTimeoutNotice()
+}
+
+func TestCodespace_GetLastKnownStopNotice(tt *testing.T) {
+	var zeroValue string
+	c := &Codespace{LastKnownStopNotice: &zeroValue}
+	c.GetLastKnownStopNotice()
+	c = &Codespace{}
+	c.GetLastKnownStopNotice()
+	c = nil
+	c.GetLastKnownStopNotice()
+}
+
+func TestCodespace_GetLastUsedAt(tt *testing.T) {
+	var zeroValue Timestamp
+	c := &Codespace{LastUsedAt: &zeroValue}
+	c.GetLastUsedAt()
+	c = &Codespace{}
+	c.GetLastUsedAt()
+	c = nil
+	c.GetLastUsedAt()
+}
+
+func TestCodespace_GetLocation(tt *testing.T) {
+	var zeroValue string
+	c := &Codespace{Location: &zeroValue}
+	c.GetLocation()
+	c = &Codespace{}
+	c.GetLocation()
+	c = nil
+	c.GetLocation()
+}
+
+func TestCodespace_GetMachine(tt *testing.T) {
+	c := &Codespace{}
+	c.GetMachine()
+	c = nil
+	c.GetMachine()
+}
+
+func TestCodespace_GetMachinesURL(tt *testing.T) {
+	var zeroValue string
+	c := &Codespace{MachinesURL: &zeroValue}
+	c.GetMachinesURL()
+	c = &Codespace{}
+	c.GetMachinesURL()
+	c = nil
+	c.GetMachinesURL()
+}
+
+func TestCodespace_GetName(tt *testing.T) {
+	var zeroValue string
+	c := &Codespace{Name: &zeroValue}
+	c.GetName()
+	c = &Codespace{}
+	c.GetName()
+	c = nil
+	c.GetName()
+}
+
+func TestCodespace_GetOwner(tt *testing.T) {
+	c := &Codespace{}
+	c.GetOwner()
+	c = nil
+	c.GetOwner()
+}
+
+func TestCodespace_GetPendingOperation(tt *testing.T) {
+	var zeroValue bool
+	c := &Codespace{PendingOperation: &zeroValue}
+	c.GetPendingOperation()
+	c = &Codespace{}
+	c.GetPendingOperation()
+	c = nil
+	c.GetPendingOperation()
+}
+
+func TestCodespace_GetPendingOperationDisabledReason(tt *testing.T) {
+	var zeroValue string
+	c := &Codespace{PendingOperationDisabledReason: &zeroValue}
+	c.GetPendingOperationDisabledReason()
+	c = &Codespace{}
+	c.GetPendingOperationDisabledReason()
+	c = nil
+	c.GetPendingOperationDisabledReason()
+}
+
+func TestCodespace_GetPrebuild(tt *testing.T) {
+	var zeroValue bool
+	c := &Codespace{Prebuild: &zeroValue}
+	c.GetPrebuild()
+	c = &Codespace{}
+	c.GetPrebuild()
+	c = nil
+	c.GetPrebuild()
+}
+
+func TestCodespace_GetPullsURL(tt *testing.T) {
+	var zeroValue string
+	c := &Codespace{PullsURL: &zeroValue}
+	c.GetPullsURL()
+	c = &Codespace{}
+	c.GetPullsURL()
+	c = nil
+	c.GetPullsURL()
+}
+
+func TestCodespace_GetRepository(tt *testing.T) {
+	c := &Codespace{}
+	c.GetRepository()
+	c = nil
+	c.GetRepository()
+}
+
+func TestCodespace_GetRetentionExpiresAt(tt *testing.T) {
+	var zeroValue Timestamp
+	c := &Codespace{RetentionExpiresAt: &zeroValue}
+	c.GetRetentionExpiresAt()
+	c = &Codespace{}
+	c.GetRetentionExpiresAt()
+	c = nil
+	c.GetRetentionExpiresAt()
+}
+
+func TestCodespace_GetRetentionPeriodMinutes(tt *testing.T) {
+	var zeroValue int
+	c := &Codespace{RetentionPeriodMinutes: &zeroValue}
+	c.GetRetentionPeriodMinutes()
+	c = &Codespace{}
+	c.GetRetentionPeriodMinutes()
+	c = nil
+	c.GetRetentionPeriodMinutes()
+}
+
+func TestCodespace_GetRuntimeConstraints(tt *testing.T) {
+	c := &Codespace{}
+	c.GetRuntimeConstraints()
+	c = nil
+	c.GetRuntimeConstraints()
+}
+
+func TestCodespace_GetStartURL(tt *testing.T) {
+	var zeroValue string
+	c := &Codespace{StartURL: &zeroValue}
+	c.GetStartURL()
+	c = &Codespace{}
+	c.GetStartURL()
+	c = nil
+	c.GetStartURL()
+}
+
+func TestCodespace_GetState(tt *testing.T) {
+	var zeroValue string
+	c := &Codespace{State: &zeroValue}
+	c.GetState()
+	c = &Codespace{}
+	c.GetState()
+	c = nil
+	c.GetState()
+}
+
+func TestCodespace_GetStopURL(tt *testing.T) {
+	var zeroValue string
+	c := &Codespace{StopURL: &zeroValue}
+	c.GetStopURL()
+	c = &Codespace{}
+	c.GetStopURL()
+	c = nil
+	c.GetStopURL()
+}
+
+func TestCodespace_GetUpdatedAt(tt *testing.T) {
+	var zeroValue Timestamp
+	c := &Codespace{UpdatedAt: &zeroValue}
+	c.GetUpdatedAt()
+	c = &Codespace{}
+	c.GetUpdatedAt()
+	c = nil
+	c.GetUpdatedAt()
+}
+
+func TestCodespace_GetURL(tt *testing.T) {
+	var zeroValue string
+	c := &Codespace{URL: &zeroValue}
+	c.GetURL()
+	c = &Codespace{}
+	c.GetURL()
+	c = nil
+	c.GetURL()
+}
+
+func TestCodespace_GetWebURL(tt *testing.T) {
+	var zeroValue string
+	c := &Codespace{WebURL: &zeroValue}
+	c.GetWebURL()
+	c = &Codespace{}
+	c.GetWebURL()
+	c = nil
+	c.GetWebURL()
+}
+
+func TestCodespacesGitStatus_GetAhead(tt *testing.T) {
+	var zeroValue int
+	c := &CodespacesGitStatus{Ahead: &zeroValue}
+	c.GetAhead()
+	c = &CodespacesGitStatus{}
+	c.GetAhead()
+	c = nil
+	c.GetAhead()
+}
+
+func TestCodespacesGitStatus_GetBehind(tt *testing.T) {
+	var zeroValue int
+	c := &CodespacesGitStatus{Behind: &zeroValue}
+	c.GetBehind()
+	c = &CodespacesGitStatus{}
+	c.GetBehind()
+	c = nil
+	c.GetBehind()
+}
+
+func TestCodespacesGitStatus_GetHasUncommittedChanges(tt *testing.T) {
+	var zeroValue bool
+	c := &CodespacesGitStatus{HasUncommittedChanges: &zeroValue}
+	c.GetHasUncommittedChanges()
+	c = &CodespacesGitStatus{}
+	c.GetHasUncommittedChanges()
+	c = nil
+	c.GetHasUncommittedChanges()
+}
+
+func TestCodespacesGitStatus_GetHasUnpushedChanges(tt *testing.T) {
+	var zeroValue bool
+	c := &CodespacesGitStatus{HasUnpushedChanges: &zeroValue}
+	c.GetHasUnpushedChanges()
+	c = &CodespacesGitStatus{}
+	c.GetHasUnpushedChanges()
+	c = nil
+	c.GetHasUnpushedChanges()
+}
+
+func TestCodespacesGitStatus_GetRef(tt *testing.T) {
+	var zeroValue string
+	c := &CodespacesGitStatus{Ref: &zeroValue}
+	c.GetRef()
+	c = &CodespacesGitStatus{}
+	c.GetRef()
+	c = nil
+	c.GetRef()
+}
+
+func TestCodespacesMachine_GetCPUs(tt *testing.T) {
+	var zeroValue int
+	c := &CodespacesMachine{CPUs: &zeroValue}
+	c.GetCPUs()
+	c = &CodespacesMachine{}
+	c.GetCPUs()
+	c = nil
+	c.GetCPUs()
+}
+
+func TestCodespacesMachine_GetDisplayName(tt *testing.T) {
+	var zeroValue string
+	c := &CodespacesMachine{DisplayName: &zeroValue}
+	c.GetDisplayName()
+	c = &CodespacesMachine{}
+	c.GetDisplayName()
+	c = nil
+	c.GetDisplayName()
+}
+
+func TestCodespacesMachine_GetMemoryInBytes(tt *testing.T) {
+	var zeroValue int64
+	c := &CodespacesMachine{MemoryInBytes: &zeroValue}
+	c.GetMemoryInBytes()
+	c = &CodespacesMachine{}
+	c.GetMemoryInBytes()
+	c = nil
+	c.GetMemoryInBytes()
+}
+
+func TestCodespacesMachine_GetName(tt *testing.T) {
+	var zeroValue string
+	c := &CodespacesMachine{Name: &zeroValue}
+	c.GetName()
+	c = &CodespacesMachine{}
+	c.GetName()
+	c = nil
+	c.GetName()
+}
+
+func TestCodespacesMachine_GetOperatingSystem(tt *testing.T) {
+	var zeroValue string
+	c := &CodespacesMachine{OperatingSystem: &zeroValue}
+	c.GetOperatingSystem()
+	c = &CodespacesMachine{}
+	c.GetOperatingSystem()
+	c = nil
+	c.GetOperatingSystem()
+}
+
+func TestCodespacesMachine_GetPrebuildAvailability(tt *testing.T) {
+	var zeroValue string
+	c := &CodespacesMachine{PrebuildAvailability: &zeroValue}
+	c.GetPrebuildAvailability()
+	c = &CodespacesMachine{}
+	c.GetPrebuildAvailability()
+	c = nil
+	c.GetPrebuildAvailability()
+}
+
+func TestCodespacesMachine_GetStorageInBytes(tt *testing.T) {
+	var zeroValue int64
+	c := &CodespacesMachine{StorageInBytes: &zeroValue}
+	c.GetStorageInBytes()
+	c = &CodespacesMachine{}
+	c.GetStorageInBytes()
+	c = nil
+	c.GetStorageInBytes()
+}
+
 func TestCollaboratorInvitation_GetCreatedAt(tt *testing.T) {
 	var zeroValue Timestamp
 	c := &CollaboratorInvitation{CreatedAt: &zeroValue}
@@ -4714,6 +5136,106 @@ func TestCreateCheckSuiteOptions_GetHeadBranch(tt *testing.T) {
 	c.GetHeadBranch()
 }
 
+func TestCreateCodespaceOptions_GetClientIP(tt *testing.T) {
+	var zeroValue string
+	c := &CreateCodespaceOptions{ClientIP: &zeroValue}
+	c.GetClientIP()
+	c = &CreateCodespaceOptions{}
+	c.GetClientIP()
+	c = nil
+	c.GetClientIP()
+}
+
+func TestCreateCodespaceOptions_GetDevcontainerPath(tt *testing.T) {
+	var zeroValue string
+	c := &CreateCodespaceOptions{DevcontainerPath: &zeroValue}
+	c.GetDevcontainerPath()
+	c = &CreateCodespaceOptions{}
+	c.GetDevcontainerPath()
+	c = nil
+	c.GetDevcontainerPath()
+}
+
+func TestCreateCodespaceOptions_GetDisplayName(tt *testing.T) {
+	var zeroValue string
+	c := &CreateCodespaceOptions{DisplayName: &zeroValue}
+	c.GetDisplayName()
+	c = &CreateCodespaceOptions{}
+	c.GetDisplayName()
+	c = nil
+	c.GetDisplayName()
+}
+
+func TestCreateCodespaceOptions_GetGeo(tt *testing.T) {
+	var zeroValue string
+	c := &CreateCodespaceOptions{Geo: &zeroValue}
+	c.GetGeo()
+	c = &CreateCodespaceOptions{}
+	c.GetGeo()
+	c = nil
+	c.GetGeo()
+}
+
+func TestCreateCodespaceOptions_GetIdleTimeoutMinutes(tt *testing.T) {
+	var zeroValue int
+	c := &CreateCodespaceOptions{IdleTimeoutMinutes: &zeroValue}
+	c.GetIdleTimeoutMinutes()
+	c = &CreateCodespaceOptions{}
+	c.GetIdleTimeoutMinutes()
+	c = nil
+	c.GetIdleTimeoutMinutes()
+}
+
+func TestCreateCodespaceOptions_GetMachine(tt *testing.T) {
+	var zeroValue string
+	c := &CreateCodespaceOptions{Machine: &zeroValue}
+	c.GetMachine()
+	c = &CreateCodespaceOptions{}
+	c.GetMachine()
+	c = nil
+	c.GetMachine()
+}
+
+func TestCreateCodespaceOptions_GetMultiRepoPermissionsOptOut(tt *testing.T) {
+	var zeroValue bool
+	c := &CreateCodespaceOptions{MultiRepoPermissionsOptOut: &zeroValue}
+	c.GetMultiRepoPermissionsOptOut()
+	c = &CreateCodespaceOptions{}
+	c.GetMultiRepoPermissionsOptOut()
+	c = nil
+	c.GetMultiRepoPermissionsOptOut()
+}
+
+func TestCreateCodespaceOptions_GetRef(tt *testing.T) {
+	var zeroValue string
+	c := &CreateCodespaceOptions{Ref: &zeroValue}
+	c.GetRef()
+	c = &CreateCodespaceOptions{}
+	c.GetRef()
+	c = nil
+	c.GetRef()
+}
+
+func TestCreateCodespaceOptions_GetRetentionPeriodMinutes(tt *testing.T) {
+	var zeroValue int
+	c := &CreateCodespaceOptions{RetentionPeriodMinutes: &zeroValue}
+	c.GetRetentionPeriodMinutes()
+	c = &CreateCodespaceOptions{}
+	c.GetRetentionPeriodMinutes()
+	c = nil
+	c.GetRetentionPeriodMinutes()
+}
+
+func TestCreateCodespaceOptions_GetWorkingDirectory(tt *testing.T) {
+	var zeroValue string
+	c := &CreateCodespaceOptions{WorkingDirectory: &zeroValue}
+	c.GetWorkingDirectory()
+	c = &CreateCodespaceOptions{}
+	c.GetWorkingDirectory()
+	c = nil
+	c.GetWorkingDirectory()
+}
+
 func TestCreateEvent_GetDescription(tt *testing.T) {
 	var zeroValue string
 	c := &CreateEvent{Description: &zeroValue}
@@ -5016,6 +5538,36 @@ func TestCustomRepoRoles_GetName(tt *testing.T) {
 	c.GetName()
 }
 
+func TestDefaultSetupConfiguration_GetQuerySuite(tt *testing.T) {
+	var zeroValue string
+	d := &DefaultSetupConfiguration{QuerySuite: &zeroValue}
+	d.GetQuerySuite()
+	d = &DefaultSetupConfiguration{}
+	d.GetQuerySuite()
+	d = nil
+	d.GetQuerySuite()
+}
+
+func TestDefaultSetupConfiguration_GetState(tt *testing.T) {
+	var zeroValue string
+	d := &DefaultSetupConfiguration{State: &zeroValue}
+	d.GetState()
+	d = &DefaultSetupConfiguration{}
+	d.GetState()
+	d = nil
+	d.GetState()
+}
+
+func TestDefaultSetupConfiguration_GetUpdatedAt(tt *testing.T) {
+	var zeroValue Timestamp
+	d := &DefaultSetupConfiguration{UpdatedAt: &zeroValue}
+	d.GetUpdatedAt()
+	d = &DefaultSetupConfiguration{}
+	d.GetUpdatedAt()
+	d = nil
+	d.GetUpdatedAt()
+}
+
 func TestDeleteEvent_GetInstallation(tt *testing.T) {
 	d := &DeleteEvent{}
 	d.GetInstallation()
@@ -7363,6 +7915,16 @@ func TestForkEvent_GetSender(tt *testing.T) {
 	f.GetSender()
 }
 
+func TestGenerateJITConfigRequest_GetWorkFolder(tt *testing.T) {
+	var zeroValue string
+	g := &GenerateJITConfigRequest{WorkFolder: &zeroValue}
+	g.GetWorkFolder()
+	g = &GenerateJITConfigRequest{}
+	g.GetWorkFolder()
+	g = nil
+	g.GetWorkFolder()
+}
+
 func TestGenerateNotesOptions_GetPreviousTagName(tt *testing.T) {
 	var zeroValue string
 	g := &GenerateNotesOptions{PreviousTagName: &zeroValue}
@@ -10457,6 +11019,16 @@ func TestIssueStats_GetTotalIssues(tt *testing.T) {
 	i.GetTotalIssues()
 }
 
+func TestJITRunnerConfig_GetEncodedJITConfig(tt *testing.T) {
+	var zeroValue string
+	j := &JITRunnerConfig{EncodedJITConfig: &zeroValue}
+	j.GetEncodedJITConfig()
+	j = &JITRunnerConfig{}
+	j.GetEncodedJITConfig()
+	j = nil
+	j.GetEncodedJITConfig()
+}
+
 func TestJobs_GetTotalCount(tt *testing.T) {
 	var zeroValue int
 	j := &Jobs{TotalCount: &zeroValue}
@@ -11086,6 +11658,16 @@ func TestListCheckSuiteResults_GetTotal(tt *testing.T) {
 	l.GetTotal()
 }
 
+func TestListCodespaces_GetTotalCount(tt *testing.T) {
+	var zeroValue int
+	l := &ListCodespaces{TotalCount: &zeroValue}
+	l.GetTotalCount()
+	l = &ListCodespaces{}
+	l.GetTotalCount()
+	l = nil
+	l.GetTotalCount()
+}
+
 func TestListCollaboratorOptions_GetAffiliation(tt *testing.T) {
 	var zeroValue string
 	l := &ListCollaboratorOptions{Affiliation: &zeroValue}
@@ -20865,6 +21447,16 @@ func TestRepositoryRelease_GetZipballURL(tt *testing.T) {
 	r.GetZipballURL()
 }
 
+func TestRepositoryRule_GetParameters(tt *testing.T) {
+	var zeroValue json.RawMessage
+	r := &RepositoryRule{Parameters: &zeroValue}
+	r.GetParameters()
+	r = &RepositoryRule{}
+	r.GetParameters()
+	r = nil
+	r.GetParameters()
+}
+
 func TestRepositoryTag_GetCommit(tt *testing.T) {
 	r := &RepositoryTag{}
 	r.GetCommit()
@@ -21404,6 +21996,131 @@ func TestRule_GetSeverity(tt *testing.T) {
 	r.GetSeverity()
 }
 
+func TestRulePatternParameters_GetName(tt *testing.T) {
+	var zeroValue string
+	r := &RulePatternParameters{Name: &zeroValue}
+	r.GetName()
+	r = &RulePatternParameters{}
+	r.GetName()
+	r = nil
+	r.GetName()
+}
+
+func TestRulePatternParameters_GetNegate(tt *testing.T) {
+	var zeroValue bool
+	r := &RulePatternParameters{Negate: &zeroValue}
+	r.GetNegate()
+	r = &RulePatternParameters{}
+	r.GetNegate()
+	r = nil
+	r.GetNegate()
+}
+
+func TestRuleRequiredStatusChecks_GetIntegrationID(tt *testing.T) {
+	var zeroValue int64
+	r := &RuleRequiredStatusChecks{IntegrationID: &zeroValue}
+	r.GetIntegrationID()
+	r = &RuleRequiredStatusChecks{}
+	r.GetIntegrationID()
+	r = nil
+	r.GetIntegrationID()
+}
+
+func TestRuleset_GetBypassMode(tt *testing.T) {
+	var zeroValue string
+	r := &Ruleset{BypassMode: &zeroValue}
+	r.GetBypassMode()
+	r = &Ruleset{}
+	r.GetBypassMode()
+	r = nil
+	r.GetBypassMode()
+}
+
+func TestRuleset_GetConditions(tt *testing.T) {
+	r := &Ruleset{}
+	r.GetConditions()
+	r = nil
+	r.GetConditions()
+}
+
+func TestRuleset_GetLinks(tt *testing.T) {
+	r := &Ruleset{}
+	r.GetLinks()
+	r = nil
+	r.GetLinks()
+}
+
+func TestRuleset_GetNodeID(tt *testing.T) {
+	var zeroValue string
+	r := &Ruleset{NodeID: &zeroValue}
+	r.GetNodeID()
+	r = &Ruleset{}
+	r.GetNodeID()
+	r = nil
+	r.GetNodeID()
+}
+
+func TestRuleset_GetSourceType(tt *testing.T) {
+	var zeroValue string
+	r := &Ruleset{SourceType: &zeroValue}
+	r.GetSourceType()
+	r = &Ruleset{}
+	r.GetSourceType()
+	r = nil
+	r.GetSourceType()
+}
+
+func TestRuleset_GetTarget(tt *testing.T) {
+	var zeroValue string
+	r := &Ruleset{Target: &zeroValue}
+	r.GetTarget()
+	r = &Ruleset{}
+	r.GetTarget()
+	r = nil
+	r.GetTarget()
+}
+
+func TestRulesetConditions_GetRefName(tt *testing.T) {
+	r := &RulesetConditions{}
+	r.GetRefName()
+	r = nil
+	r.GetRefName()
+}
+
+func TestRulesetConditions_GetRepositoryName(tt *testing.T) {
+	r := &RulesetConditions{}
+	r.GetRepositoryName()
+	r = nil
+	r.GetRepositoryName()
+}
+
+func TestRulesetLink_GetHRef(tt *testing.T) {
+	var zeroValue string
+	r := &RulesetLink{HRef: &zeroValue}
+	r.GetHRef()
+	r = &RulesetLink{}
+	r.GetHRef()
+	r = nil
+	r.GetHRef()
+}
+
+func TestRulesetLinks_GetSelf(tt *testing.T) {
+	r := &RulesetLinks{}
+	r.GetSelf()
+	r = nil
+	r.GetSelf()
+}
+
+func TestRulesetRepositoryConditionParameters_GetProtected(tt *testing.T) {
+	var zeroValue bool
+	r := &RulesetRepositoryConditionParameters{Protected: &zeroValue}
+	r.GetProtected()
+	r = &RulesetRepositoryConditionParameters{}
+	r.GetProtected()
+	r = nil
+	r.GetProtected()
+}
+
 func TestRunner_GetBusy(tt *testing.T) {
 	var zeroValue bool
 	r := &Runner{Busy: &zeroValue}
@@ -24496,6 +25213,36 @@ func TestUpdateCheckRunOptions_GetStatus(tt *testing.T) {
 	u.GetStatus()
 }
 
+func TestUpdateDefaultSetupConfigurationOptions_GetQuerySuite(tt *testing.T) {
+	var zeroValue string
+	u := &UpdateDefaultSetupConfigurationOptions{QuerySuite: &zeroValue}
+	u.GetQuerySuite()
+	u = &UpdateDefaultSetupConfigurationOptions{}
+	u.GetQuerySuite()
+	u = nil
+	u.GetQuerySuite()
+}
+
+func TestUpdateDefaultSetupConfigurationResponse_GetRunID(tt *testing.T) {
+	var zeroValue int64
+	u := &UpdateDefaultSetupConfigurationResponse{RunID: &zeroValue}
+	u.GetRunID()
+	u = &UpdateDefaultSetupConfigurationResponse{}
+	u.GetRunID()
+	u = nil
+	u.GetRunID()
+}
+
+func TestUpdateDefaultSetupConfigurationResponse_GetRunURL(tt *testing.T) {
+	var zeroValue string
+	u := &UpdateDefaultSetupConfigurationResponse{RunURL: &zeroValue}
+	u.GetRunURL()
+	u = &UpdateDefaultSetupConfigurationResponse{}
+	u.GetRunURL()
+	u = nil
+	u.GetRunURL()
+}
+
 func TestUpdateRunnerGroupRequest_GetAllowsPublicRepositories(tt *testing.T) {
 	var zeroValue bool
 	u := &UpdateRunnerGroupRequest{AllowsPublicRepositories: &zeroValue}
diff --git a/github/orgs_rules_test.go b/github/orgs_rules_test.go
new file mode 100644
index 00000000..7719e142
--- /dev/null
+++ b/github/orgs_rules_test.go
@@ -0,0 +1,628 @@
+// Copyright 2023 The go-github AUTHORS. All rights reserved.
+//
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package github
+
+import (
+	"context"
+	"fmt"
+	"net/http"
+	"testing"
+
+	"github.com/google/go-cmp/cmp"
+)
+
+func TestOrganizationsService_GetAllOrganizationRulesets(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/orgs/o/rulesets", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "GET")
+		fmt.Fprint(w, `[{
+			"id": 26110,
+			"name": "test ruleset",
+			"target": "branch",
+			"source_type": "Organization",
+			"source": "o",
+			"enforcement": "active",
+			"bypass_mode": "none",
+			"node_id": "nid",
+			"_links": {
+			  "self": {
+				"href": "https://api.github.com/orgs/o/rulesets/26110"
+			  }
+			}
+		}]`)
+	})
+
+	ctx := context.Background()
+	rulesets, _, err := client.Organizations.GetAllOrganizationRulesets(ctx, "o")
+	if err != nil {
+		t.Errorf("Organizations.GetAllOrganizationRulesets returned error: %v", err)
+	}
+
+	want := []*Ruleset{{
+		ID:          26110,
+		Name:        "test ruleset",
+		Target:      String("branch"),
+		SourceType:  String("Organization"),
+		Source:      "o",
+		Enforcement: "active",
+		BypassMode:  String("none"),
+		NodeID:      String("nid"),
+		Links: &RulesetLinks{
+			Self: &RulesetLink{HRef: String("https://api.github.com/orgs/o/rulesets/26110")},
+		},
+	}}
+	if !cmp.Equal(rulesets, want) {
+		t.Errorf("Organizations.GetAllOrganizationRulesets returned %+v, want %+v", rulesets, want)
+	}
+
+	const methodName = "GetAllOrganizationRulesets"
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		got, resp, err := client.Organizations.GetAllOrganizationRulesets(ctx, "o")
+		if got != nil {
+			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+		}
+		return resp, err
+	})
+}
+
+func TestOrganizationsService_CreateOrganizationRuleset(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/orgs/o/rulesets", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "POST")
+		fmt.Fprint(w, `{
+			"id": 21,
+			"name": "ruleset",
+			"target": "branch",
+			"source_type": "Organization",
+			"source": "o",
+			"enforcement": "active",
+			"bypass_actors": [
+			  {
+				"actor_id": 234,
+				"actor_type": "Team"
+			  }
+			],
+			"conditions": {
+			  "ref_name": {
+				"include": [
+				  "refs/heads/main",
+				  "refs/heads/master"
+				],
+				"exclude": [
+				  "refs/heads/dev*"
+				]
+			  },
+			  "repository_name": {
+				"include": [
+				  "important_repository",
+				  "another_important_repository"
+				],
+				"exclude": [
+				  "unimportant_repository"
+				],
+				"protected": true
+			  }
+			},
+			"rules": [
+			  {
+				"type": "creation"
+			  },
+			  {
+				"type": "update",
+				"parameters": {
+				  "update_allows_fetch_and_merge": true
+				}
+			  },
+			  {
+				"type": "deletion"
+			  },
+			  {
+				"type": "required_linear_history"
+			  },
+			  {
+				"type": "required_deployments",
+				"parameters": {
+				  "required_deployment_environments": ["test"]
+				}
+			  },
+			  {
+				"type": "required_signatures"
+			  },
+			  {
+				"type": "pull_request",
+				"parameters": {
+				  "dismiss_stale_reviews_on_push": true,
+				  "require_code_owner_review": true,
+				  "require_last_push_approval": true,
+				  "required_approving_review_count": 1,
+				  "required_review_thread_resolution": true
+				}
+			  },
+			  {
+				"type": "required_status_checks",
+				"parameters": {
+				  "required_status_checks": [
+					{
+					  "context": "test",
+					  "integration_id": 1
+					}
+				  ],
+				  "strict_required_status_checks_policy": true
+				}
+			  },
+			  {
+				"type": "non_fast_forward"
+			  },
+			  {
+				"type": "commit_message_pattern",
+				"parameters": {
+				  "name": "avoid test commits",
+				  "negate": true,
+				  "operator": "starts_with",
+				  "pattern": "[test]"
+				}
+			  },
+			  {
+				"type": "commit_author_email_pattern",
+				"parameters": {
+				  "operator": "contains",
+				  "pattern": "github"
+				}
+			  },
+			  {
+				"type": "committer_email_pattern",
+				"parameters": {
+				  "name": "avoid commit emails",
+				  "negate": true,
+				  "operator": "ends_with",
+				  "pattern": "abc"
+				}
+			  },
+			  {
+				"type": "branch_name_pattern",
+				"parameters": {
+				  "name": "avoid branch names",
+				  "negate": true,
+				  "operator": "regex",
+				  "pattern": "github$"
+				}
+			  },
+			  {
+				"type": "tag_name_pattern",
+				"parameters": {
+				  "name": "avoid tag names",
+				  "negate": true,
+				  "operator": "contains",
+				  "pattern": "github"
+				}
+			  }
+			]
+		  }`)
+	})
+
+	ctx := context.Background()
+	ruleset, _, err := client.Organizations.CreateOrganizationRuleset(ctx, "o", &Ruleset{
+		ID:          21,
+		Name:        "ruleset",
+		Target:      String("branch"),
+		SourceType:  String("Organization"),
+		Source:      "o",
+		Enforcement: "active",
+		BypassActors: []*BypassActor{
+			{
+				ActorID:   Int64(234),
+				ActorType: String("Team"),
+			},
+		},
+		Conditions: &RulesetConditions{
+			RefName: &RulesetRefConditionParameters{
+				Include: []string{"refs/heads/main", "refs/heads/master"},
+				Exclude: []string{"refs/heads/dev*"},
+			},
+			RepositoryName: &RulesetRepositoryConditionParameters{
+				Include:   []string{"important_repository", "another_important_repository"},
+				Exclude:   []string{"unimportant_repository"},
+				Protected: Bool(true),
+			},
+		},
+		Rules: []*RepositoryRule{
+			NewCreationRule(),
+			NewUpdateRule(&UpdateAllowsFetchAndMergeRuleParameters{
+				UpdateAllowsFetchAndMerge: true,
+			}),
+			NewDeletionRule(),
+			NewRequiredLinearHistoryRule(),
+			NewRequiredDeploymentsRule(&RequiredDeploymentEnvironmentsRuleParameters{
+				RequiredDeploymentEnvironments: []string{"test"},
+			}),
+			NewRequiredSignaturesRule(),
+			NewPullRequestRule(&PullRequestRuleParameters{
+				RequireCodeOwnerReview:         true,
+				RequireLastPushApproval:        true,
+				RequiredApprovingReviewCount:   1,
+				RequiredReviewThreadResolution: true,
+				DismissStaleReviewsOnPush:      true,
+			}),
+			NewRequiredStatusChecksRule(&RequiredStatusChecksRuleParameters{
+				RequiredStatusChecks: []RuleRequiredStatusChecks{
+					{
+						Context:       "test",
+						IntegrationID: Int64(1),
+					},
+				},
+				StrictRequiredStatusChecksPolicy: true,
+			}),
+			NewNonFastForwardRule(),
+			NewCommitMessagePatternRule(&RulePatternParameters{
+				Name:     String("avoid test commits"),
+				Negate:   Bool(true),
+				Operator: "starts_with",
+				Pattern:  "[test]",
+			}),
+			NewCommitAuthorEmailPatternRule(&RulePatternParameters{
+				Operator: "contains",
+				Pattern:  "github",
+			}),
+			NewCommitterEmailPatternRule(&RulePatternParameters{
+				Name:     String("avoid commit emails"),
+				Negate:   Bool(true),
+				Operator: "ends_with",
+				Pattern:  "abc",
+			}),
+			NewBranchNamePatternRule(&RulePatternParameters{
+				Name:     String("avoid branch names"),
+				Negate:   Bool(true),
+				Operator: "regex",
+				Pattern:  "github$",
+			}),
+			NewTagNamePatternRule(&RulePatternParameters{
+				Name:     String("avoid tag names"),
+				Negate:   Bool(true),
+				Operator: "contains",
+				Pattern:  "github",
+			}),
+		},
+	})
+	if err != nil {
+		t.Errorf("Organizations.CreateOrganizationRuleset returned error: %v", err)
+	}
+
+	want := &Ruleset{
+		ID:          21,
+		Name:        "ruleset",
+		Target:      String("branch"),
+		SourceType:  String("Organization"),
+		Source:      "o",
+		Enforcement: "active",
+		BypassActors: []*BypassActor{
+			{
+				ActorID:   Int64(234),
+				ActorType: String("Team"),
+			},
+		},
+		Conditions: &RulesetConditions{
+			RefName: &RulesetRefConditionParameters{
+				Include: []string{"refs/heads/main", "refs/heads/master"},
+				Exclude: []string{"refs/heads/dev*"},
+			},
+			RepositoryName: &RulesetRepositoryConditionParameters{
+				Include:   []string{"important_repository", "another_important_repository"},
+				Exclude:   []string{"unimportant_repository"},
+				Protected: Bool(true),
+			},
+		},
+		Rules: []*RepositoryRule{
+			NewCreationRule(),
+			NewUpdateRule(&UpdateAllowsFetchAndMergeRuleParameters{
+				UpdateAllowsFetchAndMerge: true,
+			}),
+			NewDeletionRule(),
+			NewRequiredLinearHistoryRule(),
+			NewRequiredDeploymentsRule(&RequiredDeploymentEnvironmentsRuleParameters{
+				RequiredDeploymentEnvironments: []string{"test"},
+			}),
+			NewRequiredSignaturesRule(),
+			NewPullRequestRule(&PullRequestRuleParameters{
+				RequireCodeOwnerReview:         true,
+				RequireLastPushApproval:        true,
+				RequiredApprovingReviewCount:   1,
+				RequiredReviewThreadResolution: true,
+				DismissStaleReviewsOnPush:      true,
+			}),
+			NewRequiredStatusChecksRule(&RequiredStatusChecksRuleParameters{
+				RequiredStatusChecks: []RuleRequiredStatusChecks{
+					{
+						Context:       "test",
+						IntegrationID: Int64(1),
+					},
+				},
+				StrictRequiredStatusChecksPolicy: true,
+			}),
+			NewNonFastForwardRule(),
+			NewCommitMessagePatternRule(&RulePatternParameters{
+				Name:     String("avoid test commits"),
+				Negate:   Bool(true),
+				Operator: "starts_with",
+				Pattern:  "[test]",
+			}),
+			NewCommitAuthorEmailPatternRule(&RulePatternParameters{
+				Operator: "contains",
+				Pattern:  "github",
+			}),
+			NewCommitterEmailPatternRule(&RulePatternParameters{
+				Name:     String("avoid commit emails"),
+				Negate:   Bool(true),
+				Operator: "ends_with",
+				Pattern:  "abc",
+			}),
+			NewBranchNamePatternRule(&RulePatternParameters{
+				Name:     String("avoid branch names"),
+				Negate:   Bool(true),
+				Operator: "regex",
+				Pattern:  "github$",
+			}),
+			NewTagNamePatternRule(&RulePatternParameters{
+				Name:     String("avoid tag names"),
+				Negate:   Bool(true),
+				Operator: "contains",
+				Pattern:  "github",
+			}),
+		},
+	}
+	if !cmp.Equal(ruleset, want) {
+		t.Errorf("Organizations.CreateOrganizationRuleset returned %+v, want %+v", ruleset, want)
+	}
+
+	const methodName = "CreateOrganizationRuleset"
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		got, resp, err := client.Organizations.CreateOrganizationRuleset(ctx, "o", nil)
+		if got != nil {
+			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+		}
+		return resp, err
+	})
+}
+
+func TestOrganizationsService_GetOrganizationRuleset(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/orgs/o/rulesets/26110", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "GET")
+		fmt.Fprint(w, `{
+			"id": 26110,
+			"name": "test ruleset",
+			"target": "branch",
+			"source_type": "Organization",
+			"source": "o",
+			"enforcement": "active",
+			"bypass_mode": "none",
+			"node_id": "nid",
+			"_links": {
+			  "self": {
+				"href": "https://api.github.com/orgs/o/rulesets/26110"
+			  }
+			},
+			"conditions": {
+				"ref_name": {
+				  "include": [
+					"refs/heads/main",
+					"refs/heads/master"
+				  ],
+				  "exclude": [
+					"refs/heads/dev*"
+				  ]
+				},
+				"repository_name": {
+				  "include": [
+					"important_repository",
+					"another_important_repository"
+				  ],
+				  "exclude": [
+					"unimportant_repository"
+				  ],
+				  "protected": true
+				}
+			  },
+			  "rules": [
+				{
+				  "type": "creation"
+				}
+			  ]
+		}`)
+	})
+
+	ctx := context.Background()
+	rulesets, _, err := client.Organizations.GetOrganizationRuleset(ctx, "o", 26110)
+	if err != nil {
+		t.Errorf("Organizations.GetOrganizationRepositoryRuleset returned error: %v", err)
+	}
+
+	want := &Ruleset{
+		ID:          26110,
+		Name:        "test ruleset",
+		Target:      String("branch"),
+		SourceType:  String("Organization"),
+		Source:      "o",
+		Enforcement: "active",
+		BypassMode:  String("none"),
+		NodeID:      String("nid"),
+		Links: &RulesetLinks{
+			Self: &RulesetLink{HRef: String("https://api.github.com/orgs/o/rulesets/26110")},
+		},
+		Conditions: &RulesetConditions{
+			RefName: &RulesetRefConditionParameters{
+				Include: []string{"refs/heads/main", "refs/heads/master"},
+				Exclude: []string{"refs/heads/dev*"},
+			},
+			RepositoryName: &RulesetRepositoryConditionParameters{
+				Include:   []string{"important_repository", "another_important_repository"},
+				Exclude:   []string{"unimportant_repository"},
+				Protected: Bool(true),
+			},
+		},
+		Rules: []*RepositoryRule{
+			NewCreationRule(),
+		},
+	}
+	if !cmp.Equal(rulesets, want) {
+		t.Errorf("Organizations.GetOrganizationRuleset returned %+v, want %+v", rulesets, want)
+	}
+
+	const methodName = "GetOrganizationRuleset"
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		got, resp, err := client.Organizations.GetOrganizationRuleset(ctx, "o", 26110)
+		if got != nil {
+			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+		}
+		return resp, err
+	})
+}
+
+func TestOrganizationsService_UpdateOrganizationRuleset(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/orgs/o/rulesets/26110", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "PUT")
+		fmt.Fprint(w, `{
+			"id": 26110,
+			"name": "test ruleset",
+			"target": "branch",
+			"source_type": "Organization",
+			"source": "o",
+			"enforcement": "active",
+			"bypass_mode": "none",
+			"node_id": "nid",
+			"_links": {
+			  "self": {
+				"href": "https://api.github.com/orgs/o/rulesets/26110"
+			  }
+			},
+			"conditions": {
+				"ref_name": {
+				  "include": [
+					"refs/heads/main",
+					"refs/heads/master"
+				  ],
+				  "exclude": [
+					"refs/heads/dev*"
+				  ]
+				},
+				"repository_name": {
+				  "include": [
+					"important_repository",
+					"another_important_repository"
+				  ],
+				  "exclude": [
+					"unimportant_repository"
+				  ],
+				  "protected": true
+				}
+			  },
+			  "rules": [
+				{
+				  "type": "creation"
+				}
+			  ]
+		}`)
+	})
+
+	ctx := context.Background()
+	rulesets, _, err := client.Organizations.UpdateOrganizationRuleset(ctx, "o", 26110, &Ruleset{
+		Name:        "test ruleset",
+		Target:      String("branch"),
+		Enforcement: "active",
+		BypassMode:  String("none"),
+		Conditions: &RulesetConditions{
+			RefName: &RulesetRefConditionParameters{
+				Include: []string{"refs/heads/main", "refs/heads/master"},
+				Exclude: []string{"refs/heads/dev*"},
+			},
+			RepositoryName: &RulesetRepositoryConditionParameters{
+				Include:   []string{"important_repository", "another_important_repository"},
+				Exclude:   []string{"unimportant_repository"},
+				Protected: Bool(true),
+			},
+		},
+		Rules: []*RepositoryRule{
+			NewCreationRule(),
+		},
+	})
+
+	if err != nil {
+		t.Errorf("Organizations.UpdateOrganizationRuleset returned error: %v", err)
+	}
+
+	want := &Ruleset{
+		ID:          26110,
+		Name:        "test ruleset",
+		Target:      String("branch"),
+		SourceType:  String("Organization"),
+		Source:      "o",
+		Enforcement: "active",
+		BypassMode:  String("none"),
+		NodeID:      String("nid"),
+		Links: &RulesetLinks{
+			Self: &RulesetLink{HRef: String("https://api.github.com/orgs/o/rulesets/26110")},
+		},
+		Conditions: &RulesetConditions{
+			RefName: &RulesetRefConditionParameters{
+				Include: []string{"refs/heads/main", "refs/heads/master"},
+				Exclude: []string{"refs/heads/dev*"},
+			},
+			RepositoryName: &RulesetRepositoryConditionParameters{
+				Include:   []string{"important_repository", "another_important_repository"},
+				Exclude:   []string{"unimportant_repository"},
+				Protected: Bool(true),
+			},
+		},
+		Rules: []*RepositoryRule{
+			NewCreationRule(),
+		},
+	}
+	if !cmp.Equal(rulesets, want) {
+		t.Errorf("Organizations.UpdateOrganizationRuleset returned %+v, want %+v", rulesets, want)
+	}
+
+	const methodName = "UpdateOrganizationRuleset"
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		got, resp, err := client.Organizations.UpdateOrganizationRuleset(ctx, "o", 26110, nil)
+		if got != nil {
+			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+		}
+		return resp, err
+	})
+}
+
+func TestOrganizationsService_DeleteOrganizationRuleset(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/orgs/o/rulesets/26110", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "DELETE")
+	})
+
+	ctx := context.Background()
+	_, err := client.Organizations.DeleteOrganizationRuleset(ctx, "o", 26110)
+	if err != nil {
+		t.Errorf("Organizations.DeleteOrganizationRuleset returned error: %v", err)
+	}
+
+	const methodName = "DeleteOrganizationRuleset"
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		return client.Organizations.DeleteOrganizationRuleset(ctx, "0", 26110)
+	})
+}
diff --git a/github/repos_contents_test.go b/github/repos_contents_test.go
index 29262ce2..295c2168 100644
--- a/github/repos_contents_test.go
+++ b/github/repos_contents_test.go
@@ -465,6 +465,20 @@ func TestRepositoriesService_GetContents_DirectoryWithSpaces(t *testing.T) {
 	}
 }
 
+func TestRepositoriesService_GetContents_PathWithParent(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+	mux.HandleFunc("/repos/o/r/contents/some/../directory/file.go", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "GET")
+		fmt.Fprint(w, `{}`)
+	})
+	ctx := context.Background()
+	_, _, _, err := client.Repositories.GetContents(ctx, "o", "r", "some/../directory/file.go", &RepositoryContentGetOptions{})
+	if err == nil {
+		t.Fatal("Repositories.GetContents expected error but got none")
+	}
+}
+
 func TestRepositoriesService_GetContents_DirectoryWithPlusChars(t *testing.T) {
 	client, mux, _, teardown := setup()
 	defer teardown()
diff --git a/github/repos_rules_test.go b/github/repos_rules_test.go
new file mode 100644
index 00000000..42c7a6e2
--- /dev/null
+++ b/github/repos_rules_test.go
@@ -0,0 +1,510 @@
+// Copyright 2023 The go-github AUTHORS. All rights reserved.
+//
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package github
+
+import (
+	"context"
+	"fmt"
+	"net/http"
+	"testing"
+
+	"github.com/google/go-cmp/cmp"
+)
+
+func TestRepositoryRule_UnmarshalJSON(t *testing.T) {
+	tests := map[string]struct {
+		data    string
+		want    *RepositoryRule
+		wantErr bool
+	}{
+		"Invalid JSON": {
+			data: `{`,
+			want: &RepositoryRule{
+				Type:       "",
+				Parameters: nil,
+			},
+			wantErr: true,
+		},
+		"Valid creation": {
+			data: `{"type":"creation"}`,
+			want: NewCreationRule(),
+		},
+		"Valid deletion": {
+			data: `{"type":"deletion"}`,
+			want: &RepositoryRule{
+				Type:       "deletion",
+				Parameters: nil,
+			},
+		},
+		"Valid required_linear_history": {
+			data: `{"type":"required_linear_history"}`,
+			want: &RepositoryRule{
+				Type:       "required_linear_history",
+				Parameters: nil,
+			},
+		},
+		"Valid required_signatures": {
+			data: `{"type":"required_signatures"}`,
+			want: &RepositoryRule{
+				Type:       "required_signatures",
+				Parameters: nil,
+			},
+		},
+		"Valid non_fast_forward": {
+			data: `{"type":"non_fast_forward"}`,
+			want: &RepositoryRule{
+				Type:       "non_fast_forward",
+				Parameters: nil,
+			},
+		},
+		"Valid update params": {
+			data: `{"type":"update","parameters":{"update_allows_fetch_and_merge":true}}`,
+			want: NewUpdateRule(&UpdateAllowsFetchAndMergeRuleParameters{UpdateAllowsFetchAndMerge: true}),
+		},
+		"Invalid update params": {
+			data: `{"type":"update","parameters":{"update_allows_fetch_and_merge":"true"}}`,
+			want: &RepositoryRule{
+				Type:       "update",
+				Parameters: nil,
+			},
+			wantErr: true,
+		},
+		"Valid required_deployments params": {
+			data: `{"type":"required_deployments","parameters":{"required_deployment_environments":["test"]}}`,
+			want: NewRequiredDeploymentsRule(&RequiredDeploymentEnvironmentsRuleParameters{
+				RequiredDeploymentEnvironments: []string{"test"},
+			}),
+		},
+		"Invalid required_deployments params": {
+			data: `{"type":"required_deployments","parameters":{"required_deployment_environments":true}}`,
+			want: &RepositoryRule{
+				Type:       "required_deployments",
+				Parameters: nil,
+			},
+			wantErr: true,
+		},
+		"Valid commit_message_pattern params": {
+			data: `{"type":"commit_message_pattern","parameters":{"operator":"starts_with","pattern":"github"}}`,
+			want: NewCommitMessagePatternRule(&RulePatternParameters{
+				Operator: "starts_with",
+				Pattern:  "github",
+			}),
+		},
+		"Invalid commit_message_pattern params": {
+			data: `{"type":"commit_message_pattern","parameters":{"operator":"starts_with","pattern":1}}`,
+			want: &RepositoryRule{
+				Type:       "commit_message_pattern",
+				Parameters: nil,
+			},
+			wantErr: true,
+		},
+		"Valid commit_author_email_pattern params": {
+			data: `{"type":"commit_author_email_pattern","parameters":{"operator":"starts_with","pattern":"github"}}`,
+			want: NewCommitAuthorEmailPatternRule(&RulePatternParameters{
+				Operator: "starts_with",
+				Pattern:  "github",
+			}),
+		},
+		"Invalid commit_author_email_pattern params": {
+			data: `{"type":"commit_author_email_pattern","parameters":{"operator":"starts_with","pattern":1}}`,
+			want: &RepositoryRule{
+				Type:       "commit_author_email_pattern",
+				Parameters: nil,
+			},
+			wantErr: true,
+		},
+		"Valid committer_email_pattern params": {
+			data: `{"type":"committer_email_pattern","parameters":{"operator":"starts_with","pattern":"github"}}`,
+			want: NewCommitterEmailPatternRule(&RulePatternParameters{
+				Operator: "starts_with",
+				Pattern:  "github",
+			}),
+		},
+		"Invalid committer_email_pattern params": {
+			data: `{"type":"committer_email_pattern","parameters":{"operator":"starts_with","pattern":1}}`,
+			want: &RepositoryRule{
+				Type:       "committer_email_pattern",
+				Parameters: nil,
+			},
+			wantErr: true,
+		},
+		"Valid branch_name_pattern params": {
+			data: `{"type":"branch_name_pattern","parameters":{"operator":"starts_with","pattern":"github"}}`,
+			want: NewBranchNamePatternRule(&RulePatternParameters{
+				Operator: "starts_with",
+				Pattern:  "github",
+			}),
+		},
+		"Invalid branch_name_pattern params": {
+			data: `{"type":"branch_name_pattern","parameters":{"operator":"starts_with","pattern":1}}`,
+			want: &RepositoryRule{
+				Type:       "branch_name_pattern",
+				Parameters: nil,
+			},
+			wantErr: true,
+		},
+		"Valid tag_name_pattern params": {
+			data: `{"type":"tag_name_pattern","parameters":{"operator":"starts_with","pattern":"github"}}`,
+			want: NewTagNamePatternRule(&RulePatternParameters{
+				Operator: "starts_with",
+				Pattern:  "github",
+			}),
+		},
+		"Invalid tag_name_pattern params": {
+			data: `{"type":"tag_name_pattern","parameters":{"operator":"starts_with","pattern":1}}`,
+			want: &RepositoryRule{
+				Type:       "tag_name_pattern",
+				Parameters: nil,
+			},
+			wantErr: true,
+		},
+		"Valid pull_request params": {
+			data: `{
+				"type":"pull_request",
+				"parameters":{
+					"dismiss_stale_reviews_on_push": true,
+					"require_code_owner_review": true,
+					"require_last_push_approval": true,
+					"required_approving_review_count": 1,
+					"required_review_thread_resolution":true
+				}
+			}`,
+			want: NewPullRequestRule(&PullRequestRuleParameters{
+				DismissStaleReviewsOnPush:      true,
+				RequireCodeOwnerReview:         true,
+				RequireLastPushApproval:        true,
+				RequiredApprovingReviewCount:   1,
+				RequiredReviewThreadResolution: true,
+			}),
+		},
+		"Invalid pull_request params": {
+			data: `{"type":"pull_request","parameters": {"dismiss_stale_reviews_on_push":"true"}}`,
+			want: &RepositoryRule{
+				Type:       "pull_request",
+				Parameters: nil,
+			},
+			wantErr: true,
+		},
+		"Valid required_status_checks params": {
+			data: `{"type":"required_status_checks","parameters":{"required_status_checks":[{"context":"test","integration_id":1}],"strict_required_status_checks_policy":true}}`,
+			want: NewRequiredStatusChecksRule(&RequiredStatusChecksRuleParameters{
+				RequiredStatusChecks: []RuleRequiredStatusChecks{
+					{
+						Context:       "test",
+						IntegrationID: Int64(1),
+					},
+				},
+				StrictRequiredStatusChecksPolicy: true,
+			}),
+		},
+		"Invalid required_status_checks params": {
+			data: `{"type":"required_status_checks",
+			"parameters": {
+				"required_status_checks": [
+				  {
+					"context": 1
+				  }
+				]
+			  }}`,
+			want: &RepositoryRule{
+				Type:       "required_status_checks",
+				Parameters: nil,
+			},
+			wantErr: true,
+		},
+		"Invalid type": {
+			data: `{"type":"unknown"}`,
+			want: &RepositoryRule{
+				Type:       "",
+				Parameters: nil,
+			},
+			wantErr: true,
+		},
+	}
+
+	for name, tc := range tests {
+		rule := &RepositoryRule{}
+
+		t.Run(name, func(t *testing.T) {
+			err := rule.UnmarshalJSON([]byte(tc.data))
+			if err == nil && tc.wantErr {
+				t.Errorf("RepositoryRule.UnmarshalJSON returned nil instead of an error")
+			}
+			if err != nil && !tc.wantErr {
+				t.Errorf("RepositoryRule.UnmarshalJSON returned an unexpected error: %+v", err)
+			}
+			if !cmp.Equal(tc.want, rule) {
+				t.Errorf("RepositoryRule.UnmarshalJSON expected rule %+v, got %+v", tc.want, rule)
+			}
+		})
+	}
+}
+
+func TestRepositoriesService_GetRulesForBranch(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/repos/o/repo/rules/branches/branch", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "GET")
+		fmt.Fprint(w, `[
+			{
+			  "type": "creation"
+			},
+			{
+			  "type": "update",
+			  "parameters": {
+			    "update_allows_fetch_and_merge": true
+			  }
+			}
+		]`)
+	})
+
+	ctx := context.Background()
+	rules, _, err := client.Repositories.GetRulesForBranch(ctx, "o", "repo", "branch")
+	if err != nil {
+		t.Errorf("Repositories.GetRulesForBranch returned error: %v", err)
+	}
+
+	creationRule := NewCreationRule()
+	updateRule := NewUpdateRule(&UpdateAllowsFetchAndMergeRuleParameters{
+		UpdateAllowsFetchAndMerge: true,
+	})
+
+	want := []*RepositoryRule{
+		creationRule,
+		updateRule,
+	}
+	if !cmp.Equal(rules, want) {
+		t.Errorf("Repositories.GetRulesForBranch returned %+v, want %+v", rules, want)
+	}
+
+	const methodName = "GetRulesForBranch"
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		got, resp, err := client.Repositories.GetRulesForBranch(ctx, "o", "repo", "branch")
+		if got != nil {
+			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+		}
+		return resp, err
+	})
+}
+
+func TestRepositoriesService_GetAllRulesets(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/repos/o/repo/rulesets", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "GET")
+		fmt.Fprint(w, `[
+			{
+			  "id": 42,
+			  "name": "ruleset",
+			  "source_type": "Repository",
+			  "source": "o/repo",
+			  "enforcement": "enabled"
+			},
+			{
+			  "id": 314,
+			  "name": "Another ruleset",
+			  "source_type": "Repository",
+			  "source": "o/repo",
+			  "enforcement": "enabled"
+			}
+		]`)
+	})
+
+	ctx := context.Background()
+	ruleSet, _, err := client.Repositories.GetAllRulesets(ctx, "o", "repo", false)
+	if err != nil {
+		t.Errorf("Repositories.GetAllRulesets returned error: %v", err)
+	}
+
+	want := []*Ruleset{
+		{
+			ID:          42,
+			Name:        "ruleset",
+			SourceType:  String("Repository"),
+			Source:      "o/repo",
+			Enforcement: "enabled",
+		},
+		{
+			ID:          314,
+			Name:        "Another ruleset",
+			SourceType:  String("Repository"),
+			Source:      "o/repo",
+			Enforcement: "enabled",
+		},
+	}
+	if !cmp.Equal(ruleSet, want) {
+		t.Errorf("Repositories.GetAllRulesets returned %+v, want %+v", ruleSet, want)
+	}
+
+	const methodName = "GetAllRulesets"
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		got, resp, err := client.Repositories.GetAllRulesets(ctx, "o", "repo", false)
+		if got != nil {
+			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+		}
+		return resp, err
+	})
+}
+
+func TestRepositoriesService_CreateRuleset(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/repos/o/repo/rulesets", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "POST")
+		fmt.Fprint(w, `{
+			"id": 42,
+			"name": "ruleset",
+			"source_type": "Repository",
+			"source": "o/repo",
+			"enforcement": "enabled"
+		}`)
+	})
+
+	ctx := context.Background()
+	ruleSet, _, err := client.Repositories.CreateRuleset(ctx, "o", "repo", &Ruleset{
+		Name:        "ruleset",
+		Enforcement: "enabled",
+	})
+	if err != nil {
+		t.Errorf("Repositories.CreateRuleset returned error: %v", err)
+	}
+
+	want := &Ruleset{
+		ID:          42,
+		Name:        "ruleset",
+		SourceType:  String("Repository"),
+		Source:      "o/repo",
+		Enforcement: "enabled",
+	}
+	if !cmp.Equal(ruleSet, want) {
+		t.Errorf("Repositories.CreateRuleset returned %+v, want %+v", ruleSet, want)
+	}
+
+	const methodName = "CreateRuleset"
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		got, resp, err := client.Repositories.CreateRuleset(ctx, "o", "repo", &Ruleset{})
+		if got != nil {
+			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+		}
+		return resp, err
+	})
+}
+
+func TestRepositoriesService_GetRuleset(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/repos/o/repo/rulesets/42", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "GET")
+		fmt.Fprint(w, `{
+			"id": 42,
+			"name": "ruleset",
+			"source_type": "Organization",
+			"source": "o",
+			"enforcement": "enabled"
+		}`)
+	})
+
+	ctx := context.Background()
+	ruleSet, _, err := client.Repositories.GetRuleset(ctx, "o", "repo", 42, true)
+	if err != nil {
+		t.Errorf("Repositories.GetRuleset returned error: %v", err)
+	}
+
+	want := &Ruleset{
+		ID:          42,
+		Name:        "ruleset",
+		SourceType:  String("Organization"),
+		Source:      "o",
+		Enforcement: "enabled",
+	}
+	if !cmp.Equal(ruleSet, want) {
+		t.Errorf("Repositories.GetRuleset returned %+v, want %+v", ruleSet, want)
+	}
+
+	const methodName = "GetRuleset"
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		got, resp, err := client.Repositories.GetRuleset(ctx, "o", "repo", 42, true)
+		if got != nil {
+			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+		}
+		return resp, err
+	})
+}
+
+func TestRepositoriesService_UpdateRuleset(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/repos/o/repo/rulesets/42", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "PUT")
+		fmt.Fprint(w, `{
+			"id": 42,
+			"name": "ruleset",
+			"source_type": "Repository",
+			"source": "o/repo",
+			"enforcement": "enabled"
+		}`)
+	})
+
+	ctx := context.Background()
+	ruleSet, _, err := client.Repositories.UpdateRuleset(ctx, "o", "repo", 42, &Ruleset{
+		Name:        "ruleset",
+		Enforcement: "enabled",
+	})
+	if err != nil {
+		t.Errorf("Repositories.UpdateRuleset returned error: %v", err)
+	}
+
+	want := &Ruleset{
+		ID:          42,
+		Name:        "ruleset",
+		SourceType:  String("Repository"),
+		Source:      "o/repo",
+		Enforcement: "enabled",
+	}
+	if !cmp.Equal(ruleSet, want) {
+		t.Errorf("Repositories.UpdateRuleset returned %+v, want %+v", ruleSet, want)
+	}
+
+	const methodName = "UpdateRuleset"
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		got, resp, err := client.Repositories.UpdateRuleset(ctx, "o", "repo", 42, nil)
+		if got != nil {
+			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+		}
+		return resp, err
+	})
+}
+
+func TestRepositoriesService_DeleteRuleset(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/repos/o/repo/rulesets/42", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "DELETE")
+	})
+
+	ctx := context.Background()
+	_, err := client.Repositories.DeleteRuleset(ctx, "o", "repo", 42)
+	if err != nil {
+		t.Errorf("Repositories.DeleteRuleset returned error: %v", err)
+	}
+
+	const methodName = "DeleteRuleset"
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		return client.Repositories.DeleteRuleset(ctx, "o", "repo", 42)
+	})
+}