Repository: google/go-github (go)

Issue:
GetEnterpriseRunner method appears to be missing
The docs describe the following api https://docs.github.com/en/enterprise-server@3.10/rest/actions/self-hosted-runners?apiVersion=2022-11-28#get-a-self-hosted-runner-for-an-enterprise

however the EnterpriseService does not appear to have a corresponding method https://github.com/google/go-github/blob/master/github/enterprise_actions_runners.go

Happy to raise a PR to add this capability

Pull request description:
Add support for Enterprise GetRunner
fixes #3182 

Patch:
diff --git a/README.md b/README.md
index 06922ab7..cbbcd485 100644
--- a/README.md
+++ b/README.md
@@ -101,7 +101,7 @@ For API methods that require HTTP Basic Authentication, use the
 
 #### As a GitHub App ####
 
-GitHub Apps authentication can be provided by different pkgs like [ghinstallation](https://github.com/bradleyfalzon/ghinstallation) or [go-githubauth](github.com/jferrl/go-githubauth).
+GitHub Apps authentication can be provided by different pkgs like [ghinstallation](https://github.com/bradleyfalzon/ghinstallation) or [go-githubauth](https://github.com/jferrl/go-githubauth).
 
 > **Note**: Most endpoints (ex. [`GET /rate_limit`]) require access token authentication
 > while a few others (ex. [`GET /app/hook/deliveries`]) require [JWT] authentication.
diff --git a/github/apps.go b/github/apps.go
index 6969daba..16ef758c 100644
--- a/github/apps.go
+++ b/github/apps.go
@@ -78,6 +78,7 @@ type InstallationTokenListRepoOptions struct {
 //	https://docs.github.com/rest/apps#create-an-installation-access-token-for-an-app
 type InstallationPermissions struct {
 	Actions                       *string `json:"actions,omitempty"`
+	ActionsVariables              *string `json:"actions_variables,omitempty"`
 	Administration                *string `json:"administration,omitempty"`
 	Blocking                      *string `json:"blocking,omitempty"`
 	Checks                        *string `json:"checks,omitempty"`
@@ -93,6 +94,7 @@ type InstallationPermissions struct {
 	OrganizationAdministration    *string `json:"organization_administration,omitempty"`
 	OrganizationCustomProperties  *string `json:"organization_custom_properties,omitempty"`
 	OrganizationCustomRoles       *string `json:"organization_custom_roles,omitempty"`
+	OrganizationCustomOrgRoles    *string `json:"organization_custom_org_roles,omitempty"`
 	OrganizationHooks             *string `json:"organization_hooks,omitempty"`
 	OrganizationPackages          *string `json:"organization_packages,omitempty"`
 	OrganizationPlan              *string `json:"organization_plan,omitempty"`
diff --git a/github/enterprise_actions_runners.go b/github/enterprise_actions_runners.go
index a5364815..fa345aea 100644
--- a/github/enterprise_actions_runners.go
+++ b/github/enterprise_actions_runners.go
@@ -101,6 +101,27 @@ func (s *EnterpriseService) ListRunners(ctx context.Context, enterprise string,
 	return runners, resp, nil
 }
 
+// GetRunner gets a specific self-hosted runner configured in an enterprise.
+//
+// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/self-hosted-runners#get-a-self-hosted-runner-for-an-enterprise
+//
+//meta:operation GET /enterprises/{enterprise}/actions/runners/{runner_id}
+func (s *EnterpriseService) GetRunner(ctx context.Context, enterprise string, runnerID int64) (*Runner, *Response, error) {
+	u := fmt.Sprintf("enterprises/%v/actions/runners/%v", enterprise, runnerID)
+	req, err := s.client.NewRequest("GET", u, nil)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	runner := new(Runner)
+	resp, err := s.client.Do(ctx, req, runner)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return runner, resp, nil
+}
+
 // RemoveRunner forces the removal of a self-hosted runner from an enterprise using the runner id.
 //
 // GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/actions/self-hosted-runners#delete-a-self-hosted-runner-from-an-enterprise
diff --git a/github/github-accessors.go b/github/github-accessors.go
index 421922d3..5118791c 100644
--- a/github/github-accessors.go
+++ b/github/github-accessors.go
@@ -8822,6 +8822,14 @@ func (i *InstallationPermissions) GetActions() string {
 	return *i.Actions
 }
 
+// GetActionsVariables returns the ActionsVariables field if it's non-nil, zero value otherwise.
+func (i *InstallationPermissions) GetActionsVariables() string {
+	if i == nil || i.ActionsVariables == nil {
+		return ""
+	}
+	return *i.ActionsVariables
+}
+
 // GetAdministration returns the Administration field if it's non-nil, zero value otherwise.
 func (i *InstallationPermissions) GetAdministration() string {
 	if i == nil || i.Administration == nil {
@@ -8926,6 +8934,14 @@ func (i *InstallationPermissions) GetOrganizationAdministration() string {
 	return *i.OrganizationAdministration
 }
 
+// GetOrganizationCustomOrgRoles returns the OrganizationCustomOrgRoles field if it's non-nil, zero value otherwise.
+func (i *InstallationPermissions) GetOrganizationCustomOrgRoles() string {
+	if i == nil || i.OrganizationCustomOrgRoles == nil {
+		return ""
+	}
+	return *i.OrganizationCustomOrgRoles
+}
+
 // GetOrganizationCustomProperties returns the OrganizationCustomProperties field if it's non-nil, zero value otherwise.
 func (i *InstallationPermissions) GetOrganizationCustomProperties() string {
 	if i == nil || i.OrganizationCustomProperties == nil {
@@ -20078,6 +20094,14 @@ func (r *RepositoryPermissionLevel) GetPermission() string {
 	return *r.Permission
 }
 
+// GetRoleName returns the RoleName field if it's non-nil, zero value otherwise.
+func (r *RepositoryPermissionLevel) GetRoleName() string {
+	if r == nil || r.RoleName == nil {
+		return ""
+	}
+	return *r.RoleName
+}
+
 // GetUser returns the User field.
 func (r *RepositoryPermissionLevel) GetUser() *User {
 	if r == nil {
@@ -20854,6 +20878,14 @@ func (r *RulesetConditions) GetRepositoryName() *RulesetRepositoryNamesCondition
 	return r.RepositoryName
 }
 
+// GetRepositoryProperty returns the RepositoryProperty field.
+func (r *RulesetConditions) GetRepositoryProperty() *RulesetRepositoryPropertyConditionParameters {
+	if r == nil {
+		return nil
+	}
+	return r.RepositoryProperty
+}
+
 // GetHRef returns the HRef field if it's non-nil, zero value otherwise.
 func (r *RulesetLink) GetHRef() string {
 	if r == nil || r.HRef == nil {
diff --git a/github/repos_collaborators.go b/github/repos_collaborators.go
index 15a4e77a..d6c98535 100644
--- a/github/repos_collaborators.go
+++ b/github/repos_collaborators.go
@@ -99,6 +99,8 @@ type RepositoryPermissionLevel struct {
 	Permission *string `json:"permission,omitempty"`
 
 	User *User `json:"user,omitempty"`
+
+	RoleName *string `json:"role_name,omitempty"`
 }
 
 // GetPermissionLevel retrieves the specific permission level a collaborator has for a given repository.
diff --git a/github/repos_contents.go b/github/repos_contents.go
index c4453739..97539aee 100644
--- a/github/repos_contents.go
+++ b/github/repos_contents.go
@@ -150,7 +150,11 @@ func (s *RepositoriesService) DownloadContents(ctx context.Context, owner, repo,
 				return nil, resp, fmt.Errorf("no download link found for %s", filepath)
 			}
 
-			dlResp, err := s.client.client.Get(*contents.DownloadURL)
+			dlReq, err := http.NewRequestWithContext(ctx, http.MethodGet, *contents.DownloadURL, nil)
+			if err != nil {
+				return nil, resp, err
+			}
+			dlResp, err := s.client.client.Do(dlReq)
 			if err != nil {
 				return nil, &Response{Response: dlResp}, err
 			}
@@ -188,7 +192,11 @@ func (s *RepositoriesService) DownloadContentsWithMeta(ctx context.Context, owne
 				return nil, contents, resp, fmt.Errorf("no download link found for %s", filepath)
 			}
 
-			dlResp, err := s.client.client.Get(*contents.DownloadURL)
+			dlReq, err := http.NewRequestWithContext(ctx, http.MethodGet, *contents.DownloadURL, nil)
+			if err != nil {
+				return nil, contents, resp, err
+			}
+			dlResp, err := s.client.client.Do(dlReq)
 			if err != nil {
 				return nil, contents, &Response{Response: dlResp}, err
 			}
diff --git a/github/repos_rules.go b/github/repos_rules.go
index 6f046a35..e9148f2f 100644
--- a/github/repos_rules.go
+++ b/github/repos_rules.go
@@ -48,12 +48,25 @@ type RulesetRepositoryIDsConditionParameters struct {
 	RepositoryIDs []int64 `json:"repository_ids,omitempty"`
 }
 
+// RulesetRepositoryPropertyTargetParameters represents a repository_property name and values to be used for targeting.
+type RulesetRepositoryPropertyTargetParameters struct {
+	Name   string   `json:"name"`
+	Values []string `json:"property_values"`
+}
+
+// RulesetRepositoryPropertyConditionParameters represents the conditions object for repository_property.
+type RulesetRepositoryPropertyConditionParameters struct {
+	Include []RulesetRepositoryPropertyTargetParameters `json:"include"`
+	Exclude []RulesetRepositoryPropertyTargetParameters `json:"exclude"`
+}
+
 // RulesetConditions represents the conditions object in a ruleset.
-// Set either RepositoryName or RepositoryID, not both.
+// Set either RepositoryName or RepositoryID or RepositoryProperty, not more than one.
 type RulesetConditions struct {
-	RefName        *RulesetRefConditionParameters             `json:"ref_name,omitempty"`
-	RepositoryName *RulesetRepositoryNamesConditionParameters `json:"repository_name,omitempty"`
-	RepositoryID   *RulesetRepositoryIDsConditionParameters   `json:"repository_id,omitempty"`
+	RefName            *RulesetRefConditionParameters                `json:"ref_name,omitempty"`
+	RepositoryName     *RulesetRepositoryNamesConditionParameters    `json:"repository_name,omitempty"`
+	RepositoryID       *RulesetRepositoryIDsConditionParameters      `json:"repository_id,omitempty"`
+	RepositoryProperty *RulesetRepositoryPropertyConditionParameters `json:"repository_property,omitempty"`
 }
 
 // RulePatternParameters represents the rule pattern parameters.
diff --git a/tools/go.mod b/tools/go.mod
index 26e9fe45..b2111ca5 100644
--- a/tools/go.mod
+++ b/tools/go.mod
@@ -6,7 +6,7 @@ toolchain go1.22.0
 
 require (
 	github.com/alecthomas/kong v0.9.0
-	github.com/getkin/kin-openapi v0.124.0
+	github.com/getkin/kin-openapi v0.125.0
 	github.com/google/go-cmp v0.6.0
 	github.com/google/go-github/v62 v62.0.0
 	golang.org/x/sync v0.7.0
diff --git a/tools/go.sum b/tools/go.sum
index a9e50530..fa703579 100644
--- a/tools/go.sum
+++ b/tools/go.sum
@@ -6,8 +6,8 @@ github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc
 github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/getkin/kin-openapi v0.124.0 h1:VSFNMB9C9rTKBnQ/fpyDU8ytMTr4dWI9QovSKj9kz/M=
-github.com/getkin/kin-openapi v0.124.0/go.mod h1:wb1aSZA/iWmorQP9KTAS/phLj/t17B5jT7+fS8ed9NM=
+github.com/getkin/kin-openapi v0.125.0 h1:jyQCyf2qXS1qvs2U00xQzkGCqYPhEhZDmSmVt65fXno=
+github.com/getkin/kin-openapi v0.125.0/go.mod h1:wb1aSZA/iWmorQP9KTAS/phLj/t17B5jT7+fS8ed9NM=
 github.com/go-openapi/jsonpointer v0.20.2 h1:mQc3nmndL8ZBzStEo3JYF8wzmeWffDH4VbXz58sAx6Q=
 github.com/go-openapi/jsonpointer v0.20.2/go.mod h1:bHen+N0u1KEO3YlmqOjTT9Adn1RfD91Ar825/PuiRVs=
 github.com/go-openapi/swag v0.22.8 h1:/9RjDSQ0vbFR+NyjGMkFTsA1IA0fmhKSThmfGZjicbw=


Test patch:
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 485e3978..d9e3d3ba 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -73,4 +73,4 @@ jobs:
 
     - name: Upload coverage to Codecov
       if: ${{ matrix.update-coverage }}
-      uses: codecov/codecov-action@125fc84a9a348dbcf27191600683ec096ec9021c #v4.4.1
+      uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 #v4.5.0
diff --git a/github/apps_test.go b/github/apps_test.go
index ea670344..bb060d7a 100644
--- a/github/apps_test.go
+++ b/github/apps_test.go
@@ -769,6 +769,7 @@ func TestInstallationPermissions_Marshal(t *testing.T) {
 		Metadata:                      String("md"),
 		Members:                       String("m"),
 		OrganizationAdministration:    String("oa"),
+		OrganizationCustomOrgRoles:    String("ocr"),
 		OrganizationHooks:             String("oh"),
 		OrganizationPlan:              String("op"),
 		OrganizationPreReceiveHooks:   String("opr"),
@@ -804,6 +805,7 @@ func TestInstallationPermissions_Marshal(t *testing.T) {
 		"metadata": "md",
 		"members": "m",
 		"organization_administration": "oa",
+		"organization_custom_org_roles": "ocr",
 		"organization_hooks": "oh",
 		"organization_plan": "op",
 		"organization_pre_receive_hooks": "opr",
@@ -869,6 +871,7 @@ func TestInstallation_Marshal(t *testing.T) {
 		SingleFilePaths:     []string{"s"},
 		Permissions: &InstallationPermissions{
 			Actions:                       String("a"),
+			ActionsVariables:              String("ac"),
 			Administration:                String("ad"),
 			Checks:                        String("c"),
 			Contents:                      String("co"),
@@ -879,6 +882,7 @@ func TestInstallation_Marshal(t *testing.T) {
 			Metadata:                      String("md"),
 			Members:                       String("m"),
 			OrganizationAdministration:    String("oa"),
+			OrganizationCustomOrgRoles:    String("ocr"),
 			OrganizationHooks:             String("oh"),
 			OrganizationPlan:              String("op"),
 			OrganizationPreReceiveHooks:   String("opr"),
@@ -967,6 +971,7 @@ func TestInstallation_Marshal(t *testing.T) {
 		],
 		"permissions": {
 			"actions": "a",
+			"actions_variables": "ac",
 			"administration": "ad",
 			"checks": "c",
 			"contents": "co",
@@ -977,6 +982,7 @@ func TestInstallation_Marshal(t *testing.T) {
 			"metadata": "md",
 			"members": "m",
 			"organization_administration": "oa",
+			"organization_custom_org_roles": "ocr",
 			"organization_hooks": "oh",
 			"organization_plan": "op",
 			"organization_pre_receive_hooks": "opr",
@@ -1035,6 +1041,7 @@ func TestInstallationTokenOptions_Marshal(t *testing.T) {
 		RepositoryIDs: []int64{1},
 		Permissions: &InstallationPermissions{
 			Actions:                       String("a"),
+			ActionsVariables:              String("ac"),
 			Administration:                String("ad"),
 			Checks:                        String("c"),
 			Contents:                      String("co"),
@@ -1045,6 +1052,7 @@ func TestInstallationTokenOptions_Marshal(t *testing.T) {
 			Metadata:                      String("md"),
 			Members:                       String("m"),
 			OrganizationAdministration:    String("oa"),
+			OrganizationCustomOrgRoles:    String("ocr"),
 			OrganizationHooks:             String("oh"),
 			OrganizationPlan:              String("op"),
 			OrganizationPreReceiveHooks:   String("opr"),
@@ -1073,6 +1081,7 @@ func TestInstallationTokenOptions_Marshal(t *testing.T) {
 		"repository_ids": [1],
 		"permissions": {
 			"actions": "a",
+			"actions_variables": "ac",
 			"administration": "ad",
 			"checks": "c",
 			"contents": "co",
@@ -1083,6 +1092,7 @@ func TestInstallationTokenOptions_Marshal(t *testing.T) {
 			"metadata": "md",
 			"members": "m",
 			"organization_administration": "oa",
+			"organization_custom_org_roles": "ocr",
 			"organization_hooks": "oh",
 			"organization_plan": "op",
 			"organization_pre_receive_hooks": "opr",
@@ -1118,6 +1128,7 @@ func TestInstallationToken_Marshal(t *testing.T) {
 		ExpiresAt: &Timestamp{referenceTime},
 		Permissions: &InstallationPermissions{
 			Actions:                       String("a"),
+			ActionsVariables:              String("ac"),
 			Administration:                String("ad"),
 			Checks:                        String("c"),
 			Contents:                      String("co"),
@@ -1128,6 +1139,7 @@ func TestInstallationToken_Marshal(t *testing.T) {
 			Metadata:                      String("md"),
 			Members:                       String("m"),
 			OrganizationAdministration:    String("oa"),
+			OrganizationCustomOrgRoles:    String("ocr"),
 			OrganizationHooks:             String("oh"),
 			OrganizationPlan:              String("op"),
 			OrganizationPreReceiveHooks:   String("opr"),
@@ -1164,6 +1176,7 @@ func TestInstallationToken_Marshal(t *testing.T) {
 		"expires_at": ` + referenceTimeStr + `,
 		"permissions": {
 			"actions": "a",
+			"actions_variables": "ac",
 			"administration": "ad",
 			"checks": "c",
 			"contents": "co",
@@ -1174,6 +1187,7 @@ func TestInstallationToken_Marshal(t *testing.T) {
 			"metadata": "md",
 			"members": "m",
 			"organization_administration": "oa",
+			"organization_custom_org_roles": "ocr",
 			"organization_hooks": "oh",
 			"organization_plan": "op",
 			"organization_pre_receive_hooks": "opr",
@@ -1243,6 +1257,7 @@ func TestApp_Marshal(t *testing.T) {
 		UpdatedAt:   &Timestamp{referenceTime},
 		Permissions: &InstallationPermissions{
 			Actions:                       String("a"),
+			ActionsVariables:              String("ac"),
 			Administration:                String("ad"),
 			Checks:                        String("c"),
 			Contents:                      String("co"),
@@ -1253,6 +1268,7 @@ func TestApp_Marshal(t *testing.T) {
 			Metadata:                      String("md"),
 			Members:                       String("m"),
 			OrganizationAdministration:    String("oa"),
+			OrganizationCustomOrgRoles:    String("ocr"),
 			OrganizationHooks:             String("oh"),
 			OrganizationPlan:              String("op"),
 			OrganizationPreReceiveHooks:   String("opr"),
@@ -1310,6 +1326,7 @@ func TestApp_Marshal(t *testing.T) {
 		"updated_at": ` + referenceTimeStr + `,
 		"permissions": {
 			"actions": "a",
+			"actions_variables": "ac",
 			"administration": "ad",
 			"checks": "c",
 			"contents": "co",
@@ -1320,6 +1337,7 @@ func TestApp_Marshal(t *testing.T) {
 			"metadata": "md",
 			"members": "m",
 			"organization_administration": "oa",
+			"organization_custom_org_roles": "ocr",
 			"organization_hooks": "oh",
 			"organization_plan": "op",
 			"organization_pre_receive_hooks": "opr",
diff --git a/github/enterprise_actions_runners_test.go b/github/enterprise_actions_runners_test.go
index 3bc3c737..d5efc6f7 100644
--- a/github/enterprise_actions_runners_test.go
+++ b/github/enterprise_actions_runners_test.go
@@ -145,6 +145,46 @@ func TestEnterpriseService_ListRunners(t *testing.T) {
 	})
 }
 
+func TestEnterpriseService_GetRunner(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/enterprises/e/actions/runners/23", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "GET")
+		fmt.Fprint(w, `{"id":23,"name":"MBP","os":"macos","status":"online"}`)
+	})
+
+	ctx := context.Background()
+	runner, _, err := client.Enterprise.GetRunner(ctx, "e", 23)
+	if err != nil {
+		t.Errorf("Enterprise.GetRunner returned error: %v", err)
+	}
+
+	want := &Runner{
+		ID:     Int64(23),
+		Name:   String("MBP"),
+		OS:     String("macos"),
+		Status: String("online"),
+	}
+	if !cmp.Equal(runner, want) {
+		t.Errorf("Enterprise.GetRunner returned %+v, want %+v", runner, want)
+	}
+
+	const methodName = "GetRunner"
+	testBadOptions(t, methodName, func() (err error) {
+		_, _, err = client.Enterprise.GetRunner(ctx, "\n", 23)
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		got, resp, err := client.Enterprise.GetRunner(ctx, "e", 23)
+		if got != nil {
+			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+		}
+		return resp, err
+	})
+}
+
 func TestEnterpriseService_RemoveRunner(t *testing.T) {
 	client, mux, _, teardown := setup()
 	defer teardown()
diff --git a/github/github-accessors_test.go b/github/github-accessors_test.go
index 8753c42b..03ebada6 100644
--- a/github/github-accessors_test.go
+++ b/github/github-accessors_test.go
@@ -10338,6 +10338,16 @@ func TestInstallationPermissions_GetActions(tt *testing.T) {
 	i.GetActions()
 }
 
+func TestInstallationPermissions_GetActionsVariables(tt *testing.T) {
+	var zeroValue string
+	i := &InstallationPermissions{ActionsVariables: &zeroValue}
+	i.GetActionsVariables()
+	i = &InstallationPermissions{}
+	i.GetActionsVariables()
+	i = nil
+	i.GetActionsVariables()
+}
+
 func TestInstallationPermissions_GetAdministration(tt *testing.T) {
 	var zeroValue string
 	i := &InstallationPermissions{Administration: &zeroValue}
@@ -10468,6 +10478,16 @@ func TestInstallationPermissions_GetOrganizationAdministration(tt *testing.T) {
 	i.GetOrganizationAdministration()
 }
 
+func TestInstallationPermissions_GetOrganizationCustomOrgRoles(tt *testing.T) {
+	var zeroValue string
+	i := &InstallationPermissions{OrganizationCustomOrgRoles: &zeroValue}
+	i.GetOrganizationCustomOrgRoles()
+	i = &InstallationPermissions{}
+	i.GetOrganizationCustomOrgRoles()
+	i = nil
+	i.GetOrganizationCustomOrgRoles()
+}
+
 func TestInstallationPermissions_GetOrganizationCustomProperties(tt *testing.T) {
 	var zeroValue string
 	i := &InstallationPermissions{OrganizationCustomProperties: &zeroValue}
@@ -23307,6 +23327,16 @@ func TestRepositoryPermissionLevel_GetPermission(tt *testing.T) {
 	r.GetPermission()
 }
 
+func TestRepositoryPermissionLevel_GetRoleName(tt *testing.T) {
+	var zeroValue string
+	r := &RepositoryPermissionLevel{RoleName: &zeroValue}
+	r.GetRoleName()
+	r = &RepositoryPermissionLevel{}
+	r.GetRoleName()
+	r = nil
+	r.GetRoleName()
+}
+
 func TestRepositoryPermissionLevel_GetUser(tt *testing.T) {
 	r := &RepositoryPermissionLevel{}
 	r.GetUser()
@@ -24232,6 +24262,13 @@ func TestRulesetConditions_GetRepositoryName(tt *testing.T) {
 	r.GetRepositoryName()
 }
 
+func TestRulesetConditions_GetRepositoryProperty(tt *testing.T) {
+	r := &RulesetConditions{}
+	r.GetRepositoryProperty()
+	r = nil
+	r.GetRepositoryProperty()
+}
+
 func TestRulesetLink_GetHRef(tt *testing.T) {
 	var zeroValue string
 	r := &RulesetLink{HRef: &zeroValue}
diff --git a/github/orgs_rules_test.go b/github/orgs_rules_test.go
index 0ed54ca8..d45469f2 100644
--- a/github/orgs_rules_test.go
+++ b/github/orgs_rules_test.go
@@ -395,7 +395,342 @@ func TestOrganizationsService_CreateOrganizationRuleset_RepoNames(t *testing.T)
 		return resp, err
 	})
 }
+func TestOrganizationsService_CreateOrganizationRuleset_RepoProperty(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": {
+			  "repository_property": {
+				"include": [
+					{
+						"name": "testIncludeProp",
+						"source": "custom",
+						"property_values": [
+							"true"
+						]
+					}
+				],
+				"exclude": [
+					{
+						"name": "testExcludeProp",
+						"source": "custom",
+						"property_values": [
+							"false"
+						]
+					}
+				]
+			  }
+			},
+			"rules": [
+			  {
+				"type": "creation"
+			  },
+			  {
+				"type": "update",
+				"parameters": {
+				  "update_allows_fetch_and_merge": true
+				}
+			  },
+			  {
+				"type": "deletion"
+			  },
+			  {
+				"type": "merge_queue"
+			  },
+			  {
+				"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:          Int64(21),
+		Name:        "ruleset",
+		Target:      String("branch"),
+		SourceType:  String("Organization"),
+		Source:      "o",
+		Enforcement: "active",
+		BypassActors: []*BypassActor{
+			{
+				ActorID:   Int64(234),
+				ActorType: String("Team"),
+			},
+		},
+		Conditions: &RulesetConditions{
+			RepositoryProperty: &RulesetRepositoryPropertyConditionParameters{
+				Include: []RulesetRepositoryPropertyTargetParameters{
+					{
+						Name:   "testIncludeProp",
+						Values: []string{"true"},
+					},
+				},
+				Exclude: []RulesetRepositoryPropertyTargetParameters{
+					{
+						Name:   "testExcludeProp",
+						Values: []string{"false"},
+					},
+				},
+			},
+		},
+		Rules: []*RepositoryRule{
+			NewCreationRule(),
+			NewUpdateRule(&UpdateAllowsFetchAndMergeRuleParameters{
+				UpdateAllowsFetchAndMerge: true,
+			}),
+			NewDeletionRule(),
+			NewMergeQueueRule(),
+			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:          Int64(21),
+		Name:        "ruleset",
+		Target:      String("branch"),
+		SourceType:  String("Organization"),
+		Source:      "o",
+		Enforcement: "active",
+		BypassActors: []*BypassActor{
+			{
+				ActorID:   Int64(234),
+				ActorType: String("Team"),
+			},
+		},
+		Conditions: &RulesetConditions{
+			RepositoryProperty: &RulesetRepositoryPropertyConditionParameters{
+				Include: []RulesetRepositoryPropertyTargetParameters{
+					{
+						Name:   "testIncludeProp",
+						Values: []string{"true"},
+					},
+				},
+				Exclude: []RulesetRepositoryPropertyTargetParameters{
+					{
+						Name:   "testExcludeProp",
+						Values: []string{"false"},
+					},
+				},
+			},
+		},
+		Rules: []*RepositoryRule{
+			NewCreationRule(),
+			NewUpdateRule(&UpdateAllowsFetchAndMergeRuleParameters{
+				UpdateAllowsFetchAndMerge: true,
+			}),
+			NewDeletionRule(),
+			NewMergeQueueRule(),
+			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_CreateOrganizationRuleset_RepoIDs(t *testing.T) {
 	client, mux, _, teardown := setup()
 	defer teardown()
@@ -807,6 +1142,94 @@ func TestOrganizationsService_GetOrganizationRuleset(t *testing.T) {
 	})
 }
 
+func TestOrganizationsService_GetOrganizationRulesetWithRepoPropCondition(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": {
+			  "repository_property": {
+				"exclude": [],
+				"include": [
+				  {
+					"name": "testIncludeProp",
+					"source": "custom",
+					"property_values": [
+					  "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:          Int64(26110),
+		Name:        "test ruleset",
+		Target:      String("branch"),
+		SourceType:  String("Organization"),
+		Source:      "o",
+		Enforcement: "active",
+		NodeID:      String("nid"),
+		Links: &RulesetLinks{
+			Self: &RulesetLink{HRef: String("https://api.github.com/orgs/o/rulesets/26110")},
+		},
+		Conditions: &RulesetConditions{
+			RepositoryProperty: &RulesetRepositoryPropertyConditionParameters{
+				Include: []RulesetRepositoryPropertyTargetParameters{
+					{
+						Name:   "testIncludeProp",
+						Values: []string{"true"},
+					},
+				},
+				Exclude: []RulesetRepositoryPropertyTargetParameters{},
+			},
+		},
+		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()
@@ -922,6 +1345,113 @@ func TestOrganizationsService_UpdateOrganizationRuleset(t *testing.T) {
 	})
 }
 
+func TestOrganizationsService_UpdateOrganizationRulesetWithRepoProp(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": {
+			  "repository_property": {
+				"exclude": [],
+				"include": [
+				  {
+					"name": "testIncludeProp",
+					"source": "custom",
+					"property_values": [
+					  "true"
+					]
+				  }
+				]
+			  }
+			  },
+			  "rules": [
+				{
+				  "type": "creation"
+				}
+			  ]
+		}`)
+	})
+
+	ctx := context.Background()
+	rulesets, _, err := client.Organizations.UpdateOrganizationRuleset(ctx, "o", 26110, &Ruleset{
+		Name:        "test ruleset",
+		Target:      String("branch"),
+		Enforcement: "active",
+		Conditions: &RulesetConditions{
+			RepositoryProperty: &RulesetRepositoryPropertyConditionParameters{
+				Include: []RulesetRepositoryPropertyTargetParameters{
+					{
+						Name:   "testIncludeProp",
+						Values: []string{"true"},
+					},
+				},
+				Exclude: []RulesetRepositoryPropertyTargetParameters{},
+			},
+		},
+		Rules: []*RepositoryRule{
+			NewCreationRule(),
+		},
+	})
+
+	if err != nil {
+		t.Errorf("Organizations.UpdateOrganizationRuleset returned error: %v", err)
+	}
+
+	want := &Ruleset{
+		ID:          Int64(26110),
+		Name:        "test ruleset",
+		Target:      String("branch"),
+		SourceType:  String("Organization"),
+		Source:      "o",
+		Enforcement: "active",
+		NodeID:      String("nid"),
+		Links: &RulesetLinks{
+			Self: &RulesetLink{HRef: String("https://api.github.com/orgs/o/rulesets/26110")},
+		},
+		Conditions: &RulesetConditions{
+			RepositoryProperty: &RulesetRepositoryPropertyConditionParameters{
+				Include: []RulesetRepositoryPropertyTargetParameters{
+					{
+						Name:   "testIncludeProp",
+						Values: []string{"true"},
+					},
+				},
+				Exclude: []RulesetRepositoryPropertyTargetParameters{},
+			},
+		},
+		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()