github.com/google/go-github/v74@v74.0.0/github/orgs_rules_test.go (about)

     1  // Copyright 2023 The go-github AUTHORS. All rights reserved.
     2  //
     3  // Use of this source code is governed by a BSD-style
     4  // license that can be found in the LICENSE file.
     5  
     6  package github
     7  
     8  import (
     9  	"context"
    10  	"fmt"
    11  	"net/http"
    12  	"testing"
    13  
    14  	"github.com/google/go-cmp/cmp"
    15  )
    16  
    17  func TestOrganizationsService_GetAllRepositoryRulesets(t *testing.T) {
    18  	t.Parallel()
    19  	client, mux, _ := setup(t)
    20  
    21  	mux.HandleFunc("/orgs/o/rulesets", func(w http.ResponseWriter, r *http.Request) {
    22  		testMethod(t, r, "GET")
    23  		fmt.Fprint(w, `[{
    24  			"id": 21,
    25  			"name": "test ruleset",
    26  			"target": "branch",
    27  			"source_type": "Organization",
    28  			"source": "o",
    29  			"enforcement": "active",
    30  			"bypass_mode": "none",
    31  			"node_id": "nid",
    32  			"_links": {
    33  			  "self": {
    34  				"href": "https://api.github.com/orgs/o/rulesets/21"
    35  			  }
    36  			}
    37  		}]`)
    38  	})
    39  
    40  	ctx := context.Background()
    41  	rulesets, _, err := client.Organizations.GetAllRepositoryRulesets(ctx, "o", nil)
    42  	if err != nil {
    43  		t.Errorf("Organizations.GetAllRepositoryRulesets returned error: %v", err)
    44  	}
    45  
    46  	want := []*RepositoryRuleset{{
    47  		ID:          Ptr(int64(21)),
    48  		Name:        "test ruleset",
    49  		Target:      Ptr(RulesetTargetBranch),
    50  		SourceType:  Ptr(RulesetSourceTypeOrganization),
    51  		Source:      "o",
    52  		Enforcement: "active",
    53  		NodeID:      Ptr("nid"),
    54  		Links: &RepositoryRulesetLinks{
    55  			Self: &RepositoryRulesetLink{HRef: Ptr("https://api.github.com/orgs/o/rulesets/21")},
    56  		},
    57  	}}
    58  	if !cmp.Equal(rulesets, want) {
    59  		t.Errorf("Organizations.GetAllRepositoryRulesets returned %+v, want %+v", rulesets, want)
    60  	}
    61  
    62  	const methodName = "GetAllRepositoryRulesets"
    63  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
    64  		got, resp, err := client.Organizations.GetAllRepositoryRulesets(ctx, "o", nil)
    65  		if got != nil {
    66  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
    67  		}
    68  		return resp, err
    69  	})
    70  }
    71  
    72  func TestOrganizationsService_GetAllRepositoryRulesets_ListOptions(t *testing.T) {
    73  	t.Parallel()
    74  	client, mux, _ := setup(t)
    75  
    76  	mux.HandleFunc("/orgs/o/rulesets", func(w http.ResponseWriter, r *http.Request) {
    77  		testMethod(t, r, "GET")
    78  		testFormValues(t, r, values{
    79  			"page":     "2",
    80  			"per_page": "35",
    81  		})
    82  		fmt.Fprint(w, `[{
    83  			"id": 21
    84  		}]`)
    85  	})
    86  
    87  	opts := &ListOptions{Page: 2, PerPage: 35}
    88  	ctx := context.Background()
    89  	rulesets, _, err := client.Organizations.GetAllRepositoryRulesets(ctx, "o", opts)
    90  	if err != nil {
    91  		t.Errorf("Organizations.GetAllRepositoryRulesets returned error: %v", err)
    92  	}
    93  
    94  	want := []*RepositoryRuleset{{
    95  		ID: Ptr(int64(21)),
    96  	}}
    97  	if !cmp.Equal(rulesets, want) {
    98  		t.Errorf("Organizations.GetAllRepositoryRulesets returned %+v, want %+v", rulesets, want)
    99  	}
   100  
   101  	const methodName = "GetAllRepositoryRulesets"
   102  	testBadOptions(t, methodName, func() (err error) {
   103  		_, _, err = client.Organizations.GetAllRepositoryRulesets(ctx, "\n", opts)
   104  		return err
   105  	})
   106  
   107  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   108  		got, resp, err := client.Organizations.GetAllRepositoryRulesets(ctx, "o", opts)
   109  		if got != nil {
   110  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   111  		}
   112  		return resp, err
   113  	})
   114  }
   115  
   116  func TestOrganizationsService_CreateRepositoryRuleset_RepoNames(t *testing.T) {
   117  	t.Parallel()
   118  	client, mux, _ := setup(t)
   119  
   120  	mux.HandleFunc("/orgs/o/rulesets", func(w http.ResponseWriter, r *http.Request) {
   121  		testMethod(t, r, "POST")
   122  		fmt.Fprint(w, `{
   123  			"id": 21,
   124  			"name": "ruleset",
   125  			"target": "branch",
   126  			"source_type": "Organization",
   127  			"source": "o",
   128  			"enforcement": "active",
   129  			"bypass_actors": [
   130  			  {
   131  				"actor_id": 234,
   132  				"actor_type": "Team"
   133  			  }
   134  			],
   135  			"conditions": {
   136  			  "ref_name": {
   137  				"include": [
   138  				  "refs/heads/main",
   139  				  "refs/heads/master"
   140  				],
   141  				"exclude": [
   142  				  "refs/heads/dev*"
   143  				]
   144  			  },
   145  			  "repository_name": {
   146  				"include": [
   147  				  "important_repository",
   148  				  "another_important_repository"
   149  				],
   150  				"exclude": [
   151  				  "unimportant_repository"
   152  				],
   153  				"protected": true
   154  			  }
   155  			},
   156  			"rules": [
   157  			  {
   158  				"type": "creation"
   159  			  },
   160  			  {
   161  				"type": "update",
   162  				"parameters": {
   163  				  "update_allows_fetch_and_merge": true
   164  				}
   165  			  },
   166  			  {
   167  				"type": "deletion"
   168  			  },
   169  			  {
   170  				"type": "required_linear_history"
   171  			  },
   172  			  {
   173  				"type": "required_deployments",
   174  				"parameters": {
   175  				  "required_deployment_environments": ["test"]
   176  				}
   177  			  },
   178  			  {
   179  				"type": "required_signatures"
   180  			  },
   181  			  {
   182  				"type": "pull_request",
   183  				"parameters": {
   184  				"allowed_merge_methods": ["rebase","squash"],
   185  				  "dismiss_stale_reviews_on_push": true,
   186  				  "require_code_owner_review": true,
   187  				  "require_last_push_approval": true,
   188  				  "required_approving_review_count": 1,
   189  				  "required_review_thread_resolution": true
   190  				}
   191  			  },
   192  			  {
   193  				"type": "required_status_checks",
   194  				"parameters": {
   195  					"do_not_enforce_on_create": true,
   196  				  "required_status_checks": [
   197  					{
   198  					  "context": "test",
   199  					  "integration_id": 1
   200  					}
   201  				  ],
   202  				  "strict_required_status_checks_policy": true
   203  				}
   204  			  },
   205  			  {
   206  				"type": "non_fast_forward"
   207  			  },
   208  			  {
   209  				"type": "commit_message_pattern",
   210  				"parameters": {
   211  				  "name": "avoid test commits",
   212  				  "negate": true,
   213  				  "operator": "starts_with",
   214  				  "pattern": "[test]"
   215  				}
   216  			  },
   217  			  {
   218  				"type": "commit_author_email_pattern",
   219  				"parameters": {
   220  				  "operator": "contains",
   221  				  "pattern": "github"
   222  				}
   223  			  },
   224  			  {
   225  				"type": "committer_email_pattern",
   226  				"parameters": {
   227  				  "name": "avoid commit emails",
   228  				  "negate": true,
   229  				  "operator": "ends_with",
   230  				  "pattern": "abc"
   231  				}
   232  			  },
   233  			  {
   234  				"type": "branch_name_pattern",
   235  				"parameters": {
   236  				  "name": "avoid branch names",
   237  				  "negate": true,
   238  				  "operator": "regex",
   239  				  "pattern": "github$"
   240  				}
   241  			  },
   242  			  {
   243  				"type": "tag_name_pattern",
   244  				"parameters": {
   245  				  "name": "avoid tag names",
   246  				  "negate": true,
   247  				  "operator": "contains",
   248  				  "pattern": "github"
   249  				}
   250  			  },
   251  			  {
   252  			    "type": "code_scanning",
   253  			    "parameters": {
   254  				  "code_scanning_tools": [
   255  				    {
   256  					  "tool": "CodeQL",
   257  					  "security_alerts_threshold": "high_or_higher",
   258  					  "alerts_threshold": "errors"
   259  				    }
   260  				  ]
   261  			    }
   262  			  }
   263  			]
   264  		  }`)
   265  	})
   266  
   267  	ctx := context.Background()
   268  	ruleset, _, err := client.Organizations.CreateRepositoryRuleset(ctx, "o", RepositoryRuleset{
   269  		Name:        "ruleset",
   270  		Target:      Ptr(RulesetTargetBranch),
   271  		Enforcement: "active",
   272  		BypassActors: []*BypassActor{
   273  			{
   274  				ActorID:   Ptr(int64(234)),
   275  				ActorType: Ptr(BypassActorTypeTeam),
   276  			},
   277  		},
   278  		Conditions: &RepositoryRulesetConditions{
   279  			RefName: &RepositoryRulesetRefConditionParameters{
   280  				Include: []string{"refs/heads/main", "refs/heads/master"},
   281  				Exclude: []string{"refs/heads/dev*"},
   282  			},
   283  			RepositoryName: &RepositoryRulesetRepositoryNamesConditionParameters{
   284  				Include:   []string{"important_repository", "another_important_repository"},
   285  				Exclude:   []string{"unimportant_repository"},
   286  				Protected: Ptr(true),
   287  			},
   288  		},
   289  		Rules: &RepositoryRulesetRules{
   290  			Creation: &EmptyRuleParameters{},
   291  			Update: &UpdateRuleParameters{
   292  				UpdateAllowsFetchAndMerge: true,
   293  			},
   294  			Deletion:              &EmptyRuleParameters{},
   295  			RequiredLinearHistory: &EmptyRuleParameters{},
   296  			RequiredDeployments: &RequiredDeploymentsRuleParameters{
   297  				RequiredDeploymentEnvironments: []string{"test"},
   298  			},
   299  			RequiredSignatures: &EmptyRuleParameters{},
   300  			PullRequest: &PullRequestRuleParameters{
   301  				AllowedMergeMethods:            []PullRequestMergeMethod{PullRequestMergeMethodRebase, PullRequestMergeMethodSquash},
   302  				DismissStaleReviewsOnPush:      true,
   303  				RequireCodeOwnerReview:         true,
   304  				RequireLastPushApproval:        true,
   305  				RequiredApprovingReviewCount:   1,
   306  				RequiredReviewThreadResolution: true,
   307  			},
   308  			RequiredStatusChecks: &RequiredStatusChecksRuleParameters{
   309  				DoNotEnforceOnCreate: Ptr(true),
   310  				RequiredStatusChecks: []*RuleStatusCheck{
   311  					{
   312  						Context:       "test",
   313  						IntegrationID: Ptr(int64(1)),
   314  					},
   315  				},
   316  				StrictRequiredStatusChecksPolicy: true,
   317  			},
   318  			NonFastForward: &EmptyRuleParameters{},
   319  			CommitMessagePattern: &PatternRuleParameters{
   320  				Name:     Ptr("avoid test commits"),
   321  				Negate:   Ptr(true),
   322  				Operator: "starts_with",
   323  				Pattern:  "[test]",
   324  			},
   325  			CommitAuthorEmailPattern: &PatternRuleParameters{
   326  				Operator: "contains",
   327  				Pattern:  "github",
   328  			},
   329  			CommitterEmailPattern: &PatternRuleParameters{
   330  				Name:     Ptr("avoid commit emails"),
   331  				Negate:   Ptr(true),
   332  				Operator: "ends_with",
   333  				Pattern:  "abc",
   334  			},
   335  			BranchNamePattern: &PatternRuleParameters{
   336  				Name:     Ptr("avoid branch names"),
   337  				Negate:   Ptr(true),
   338  				Operator: "regex",
   339  				Pattern:  "github$",
   340  			},
   341  			TagNamePattern: &PatternRuleParameters{
   342  				Name:     Ptr("avoid tag names"),
   343  				Negate:   Ptr(true),
   344  				Operator: "contains",
   345  				Pattern:  "github",
   346  			},
   347  			CodeScanning: &CodeScanningRuleParameters{
   348  				CodeScanningTools: []*RuleCodeScanningTool{
   349  					{
   350  						AlertsThreshold:         CodeScanningAlertsThresholdErrors,
   351  						SecurityAlertsThreshold: CodeScanningSecurityAlertsThresholdHighOrHigher,
   352  						Tool:                    "CodeQL",
   353  					},
   354  				},
   355  			},
   356  		},
   357  	})
   358  	if err != nil {
   359  		t.Errorf("Organizations.CreateRepositoryRuleset returned error: %v", err)
   360  	}
   361  
   362  	want := &RepositoryRuleset{
   363  		ID:          Ptr(int64(21)),
   364  		Name:        "ruleset",
   365  		Target:      Ptr(RulesetTargetBranch),
   366  		SourceType:  Ptr(RulesetSourceTypeOrganization),
   367  		Source:      "o",
   368  		Enforcement: "active",
   369  		BypassActors: []*BypassActor{
   370  			{
   371  				ActorID:   Ptr(int64(234)),
   372  				ActorType: Ptr(BypassActorTypeTeam),
   373  			},
   374  		},
   375  		Conditions: &RepositoryRulesetConditions{
   376  			RefName: &RepositoryRulesetRefConditionParameters{
   377  				Include: []string{"refs/heads/main", "refs/heads/master"},
   378  				Exclude: []string{"refs/heads/dev*"},
   379  			},
   380  			RepositoryName: &RepositoryRulesetRepositoryNamesConditionParameters{
   381  				Include:   []string{"important_repository", "another_important_repository"},
   382  				Exclude:   []string{"unimportant_repository"},
   383  				Protected: Ptr(true),
   384  			},
   385  		},
   386  		Rules: &RepositoryRulesetRules{
   387  			Creation: &EmptyRuleParameters{},
   388  			Update: &UpdateRuleParameters{
   389  				UpdateAllowsFetchAndMerge: true,
   390  			},
   391  			Deletion:              &EmptyRuleParameters{},
   392  			RequiredLinearHistory: &EmptyRuleParameters{},
   393  			RequiredDeployments: &RequiredDeploymentsRuleParameters{
   394  				RequiredDeploymentEnvironments: []string{"test"},
   395  			},
   396  			RequiredSignatures: &EmptyRuleParameters{},
   397  			PullRequest: &PullRequestRuleParameters{
   398  				AllowedMergeMethods:            []PullRequestMergeMethod{PullRequestMergeMethodRebase, PullRequestMergeMethodSquash},
   399  				DismissStaleReviewsOnPush:      true,
   400  				RequireCodeOwnerReview:         true,
   401  				RequireLastPushApproval:        true,
   402  				RequiredApprovingReviewCount:   1,
   403  				RequiredReviewThreadResolution: true,
   404  			},
   405  			RequiredStatusChecks: &RequiredStatusChecksRuleParameters{
   406  				DoNotEnforceOnCreate: Ptr(true),
   407  				RequiredStatusChecks: []*RuleStatusCheck{
   408  					{
   409  						Context:       "test",
   410  						IntegrationID: Ptr(int64(1)),
   411  					},
   412  				},
   413  				StrictRequiredStatusChecksPolicy: true,
   414  			},
   415  			NonFastForward: &EmptyRuleParameters{},
   416  			CommitMessagePattern: &PatternRuleParameters{
   417  				Name:     Ptr("avoid test commits"),
   418  				Negate:   Ptr(true),
   419  				Operator: "starts_with",
   420  				Pattern:  "[test]",
   421  			},
   422  			CommitAuthorEmailPattern: &PatternRuleParameters{
   423  				Operator: "contains",
   424  				Pattern:  "github",
   425  			},
   426  			CommitterEmailPattern: &PatternRuleParameters{
   427  				Name:     Ptr("avoid commit emails"),
   428  				Negate:   Ptr(true),
   429  				Operator: "ends_with",
   430  				Pattern:  "abc",
   431  			},
   432  			BranchNamePattern: &PatternRuleParameters{
   433  				Name:     Ptr("avoid branch names"),
   434  				Negate:   Ptr(true),
   435  				Operator: "regex",
   436  				Pattern:  "github$",
   437  			},
   438  			TagNamePattern: &PatternRuleParameters{
   439  				Name:     Ptr("avoid tag names"),
   440  				Negate:   Ptr(true),
   441  				Operator: "contains",
   442  				Pattern:  "github",
   443  			},
   444  			CodeScanning: &CodeScanningRuleParameters{
   445  				CodeScanningTools: []*RuleCodeScanningTool{
   446  					{
   447  						AlertsThreshold:         CodeScanningAlertsThresholdErrors,
   448  						SecurityAlertsThreshold: CodeScanningSecurityAlertsThresholdHighOrHigher,
   449  						Tool:                    "CodeQL",
   450  					},
   451  				},
   452  			},
   453  		},
   454  	}
   455  	if !cmp.Equal(ruleset, want) {
   456  		t.Errorf("Organizations.CreateRepositoryRuleset returned %+v, want %+v", ruleset, want)
   457  	}
   458  
   459  	const methodName = "CreateRepositoryRuleset"
   460  
   461  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   462  		got, resp, err := client.Organizations.CreateRepositoryRuleset(ctx, "o", RepositoryRuleset{})
   463  		if got != nil {
   464  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   465  		}
   466  		return resp, err
   467  	})
   468  }
   469  
   470  func TestOrganizationsService_CreateRepositoryRuleset_RepoProperty(t *testing.T) {
   471  	t.Parallel()
   472  	client, mux, _ := setup(t)
   473  
   474  	mux.HandleFunc("/orgs/o/rulesets", func(w http.ResponseWriter, r *http.Request) {
   475  		testMethod(t, r, "POST")
   476  		fmt.Fprint(w, `{
   477  			"id": 21,
   478  			"name": "ruleset",
   479  			"target": "branch",
   480  			"source_type": "Organization",
   481  			"source": "o",
   482  			"enforcement": "active",
   483  			"bypass_actors": [
   484  			  {
   485  				"actor_id": 234,
   486  				"actor_type": "Team"
   487  			  }
   488  			],
   489  			"conditions": {
   490  			  "repository_property": {
   491  				"include": [
   492  					{
   493  						"name": "testIncludeProp",
   494  						"source": "custom",
   495  						"property_values": [
   496  							"true"
   497  						]
   498  					}
   499  				],
   500  				"exclude": [
   501  					{
   502  						"name": "testExcludeProp",
   503  						"property_values": [
   504  							"false"
   505  						]
   506  					}
   507  				]
   508  			  }
   509  			},
   510  			"rules": [
   511  			  {
   512  				"type": "creation"
   513  			  },
   514  			  {
   515  				"type": "update",
   516  				"parameters": {
   517  				  "update_allows_fetch_and_merge": true
   518  				}
   519  			  },
   520  			  {
   521  				"type": "deletion"
   522  			  },
   523  			  {
   524  				"type": "required_linear_history"
   525  			  },
   526  			  {
   527  				"type": "required_deployments",
   528  				"parameters": {
   529  				  "required_deployment_environments": ["test"]
   530  				}
   531  			  },
   532  			  {
   533  				"type": "required_signatures"
   534  			  },
   535  			  {
   536  				"type": "pull_request",
   537  				"parameters": {
   538  				"allowed_merge_methods": ["rebase","squash"],
   539  				  "dismiss_stale_reviews_on_push": true,
   540  				  "require_code_owner_review": true,
   541  				  "require_last_push_approval": true,
   542  				  "required_approving_review_count": 1,
   543  				  "required_review_thread_resolution": true
   544  				}
   545  			  },
   546  			  {
   547  				"type": "required_status_checks",
   548  				"parameters": {
   549  					"do_not_enforce_on_create": true,
   550  				  "required_status_checks": [
   551  					{
   552  					  "context": "test",
   553  					  "integration_id": 1
   554  					}
   555  				  ],
   556  				  "strict_required_status_checks_policy": true
   557  				}
   558  			  },
   559  			  {
   560  				"type": "non_fast_forward"
   561  			  },
   562  			  {
   563  				"type": "commit_message_pattern",
   564  				"parameters": {
   565  				  "name": "avoid test commits",
   566  				  "negate": true,
   567  				  "operator": "starts_with",
   568  				  "pattern": "[test]"
   569  				}
   570  			  },
   571  			  {
   572  				"type": "commit_author_email_pattern",
   573  				"parameters": {
   574  				  "operator": "contains",
   575  				  "pattern": "github"
   576  				}
   577  			  },
   578  			  {
   579  				"type": "committer_email_pattern",
   580  				"parameters": {
   581  				  "name": "avoid commit emails",
   582  				  "negate": true,
   583  				  "operator": "ends_with",
   584  				  "pattern": "abc"
   585  				}
   586  			  },
   587  			  {
   588  				"type": "branch_name_pattern",
   589  				"parameters": {
   590  				  "name": "avoid branch names",
   591  				  "negate": true,
   592  				  "operator": "regex",
   593  				  "pattern": "github$"
   594  				}
   595  			  },
   596  			  {
   597  				"type": "tag_name_pattern",
   598  				"parameters": {
   599  				  "name": "avoid tag names",
   600  				  "negate": true,
   601  				  "operator": "contains",
   602  				  "pattern": "github"
   603  				}
   604  			  },
   605  			  {
   606  			    "type": "code_scanning",
   607  			    "parameters": {
   608  				  "code_scanning_tools": [
   609  				    {
   610  					  "tool": "CodeQL",
   611  					  "security_alerts_threshold": "high_or_higher",
   612  					  "alerts_threshold": "errors"
   613  				    }
   614  				  ]
   615  			    }
   616  			  }
   617  			]
   618  		  }`)
   619  	})
   620  
   621  	ctx := context.Background()
   622  	ruleset, _, err := client.Organizations.CreateRepositoryRuleset(ctx, "o", RepositoryRuleset{
   623  		Name:        "ruleset",
   624  		Target:      Ptr(RulesetTargetBranch),
   625  		Enforcement: "active",
   626  		BypassActors: []*BypassActor{
   627  			{
   628  				ActorID:   Ptr(int64(234)),
   629  				ActorType: Ptr(BypassActorTypeTeam),
   630  			},
   631  		},
   632  		Conditions: &RepositoryRulesetConditions{
   633  			RepositoryProperty: &RepositoryRulesetRepositoryPropertyConditionParameters{
   634  				Include: []*RepositoryRulesetRepositoryPropertyTargetParameters{
   635  					{
   636  						Name:           "testIncludeProp",
   637  						Source:         Ptr("custom"),
   638  						PropertyValues: []string{"true"},
   639  					},
   640  				},
   641  				Exclude: []*RepositoryRulesetRepositoryPropertyTargetParameters{
   642  					{
   643  						Name:           "testExcludeProp",
   644  						PropertyValues: []string{"false"},
   645  					},
   646  				},
   647  			},
   648  		},
   649  		Rules: &RepositoryRulesetRules{
   650  			Creation: &EmptyRuleParameters{},
   651  			Update: &UpdateRuleParameters{
   652  				UpdateAllowsFetchAndMerge: true,
   653  			},
   654  			Deletion:              &EmptyRuleParameters{},
   655  			RequiredLinearHistory: &EmptyRuleParameters{},
   656  			RequiredDeployments: &RequiredDeploymentsRuleParameters{
   657  				RequiredDeploymentEnvironments: []string{"test"},
   658  			},
   659  			RequiredSignatures: &EmptyRuleParameters{},
   660  			PullRequest: &PullRequestRuleParameters{
   661  				AllowedMergeMethods:            []PullRequestMergeMethod{PullRequestMergeMethodRebase, PullRequestMergeMethodSquash},
   662  				DismissStaleReviewsOnPush:      true,
   663  				RequireCodeOwnerReview:         true,
   664  				RequireLastPushApproval:        true,
   665  				RequiredApprovingReviewCount:   1,
   666  				RequiredReviewThreadResolution: true,
   667  			},
   668  			RequiredStatusChecks: &RequiredStatusChecksRuleParameters{
   669  				DoNotEnforceOnCreate: Ptr(true),
   670  				RequiredStatusChecks: []*RuleStatusCheck{
   671  					{
   672  						Context:       "test",
   673  						IntegrationID: Ptr(int64(1)),
   674  					},
   675  				},
   676  				StrictRequiredStatusChecksPolicy: true,
   677  			},
   678  			NonFastForward: &EmptyRuleParameters{},
   679  			CommitMessagePattern: &PatternRuleParameters{
   680  				Name:     Ptr("avoid test commits"),
   681  				Negate:   Ptr(true),
   682  				Operator: "starts_with",
   683  				Pattern:  "[test]",
   684  			},
   685  			CommitAuthorEmailPattern: &PatternRuleParameters{
   686  				Operator: "contains",
   687  				Pattern:  "github",
   688  			},
   689  			CommitterEmailPattern: &PatternRuleParameters{
   690  				Name:     Ptr("avoid commit emails"),
   691  				Negate:   Ptr(true),
   692  				Operator: "ends_with",
   693  				Pattern:  "abc",
   694  			},
   695  			BranchNamePattern: &PatternRuleParameters{
   696  				Name:     Ptr("avoid branch names"),
   697  				Negate:   Ptr(true),
   698  				Operator: "regex",
   699  				Pattern:  "github$",
   700  			},
   701  			TagNamePattern: &PatternRuleParameters{
   702  				Name:     Ptr("avoid tag names"),
   703  				Negate:   Ptr(true),
   704  				Operator: "contains",
   705  				Pattern:  "github",
   706  			},
   707  			CodeScanning: &CodeScanningRuleParameters{
   708  				CodeScanningTools: []*RuleCodeScanningTool{
   709  					{
   710  						AlertsThreshold:         CodeScanningAlertsThresholdErrors,
   711  						SecurityAlertsThreshold: CodeScanningSecurityAlertsThresholdHighOrHigher,
   712  						Tool:                    "CodeQL",
   713  					},
   714  				},
   715  			},
   716  		},
   717  	})
   718  	if err != nil {
   719  		t.Errorf("Organizations.CreateRepositoryRuleset returned error: %v", err)
   720  	}
   721  
   722  	want := &RepositoryRuleset{
   723  		ID:          Ptr(int64(21)),
   724  		Name:        "ruleset",
   725  		Target:      Ptr(RulesetTargetBranch),
   726  		SourceType:  Ptr(RulesetSourceTypeOrganization),
   727  		Source:      "o",
   728  		Enforcement: "active",
   729  		BypassActors: []*BypassActor{
   730  			{
   731  				ActorID:   Ptr(int64(234)),
   732  				ActorType: Ptr(BypassActorTypeTeam),
   733  			},
   734  		},
   735  		Conditions: &RepositoryRulesetConditions{
   736  			RepositoryProperty: &RepositoryRulesetRepositoryPropertyConditionParameters{
   737  				Include: []*RepositoryRulesetRepositoryPropertyTargetParameters{
   738  					{
   739  						Name:           "testIncludeProp",
   740  						Source:         Ptr("custom"),
   741  						PropertyValues: []string{"true"},
   742  					},
   743  				},
   744  				Exclude: []*RepositoryRulesetRepositoryPropertyTargetParameters{
   745  					{
   746  						Name:           "testExcludeProp",
   747  						PropertyValues: []string{"false"},
   748  					},
   749  				},
   750  			},
   751  		},
   752  		Rules: &RepositoryRulesetRules{
   753  			Creation: &EmptyRuleParameters{},
   754  			Update: &UpdateRuleParameters{
   755  				UpdateAllowsFetchAndMerge: true,
   756  			},
   757  			Deletion:              &EmptyRuleParameters{},
   758  			RequiredLinearHistory: &EmptyRuleParameters{},
   759  			RequiredDeployments: &RequiredDeploymentsRuleParameters{
   760  				RequiredDeploymentEnvironments: []string{"test"},
   761  			},
   762  			RequiredSignatures: &EmptyRuleParameters{},
   763  			PullRequest: &PullRequestRuleParameters{
   764  				AllowedMergeMethods:            []PullRequestMergeMethod{PullRequestMergeMethodRebase, PullRequestMergeMethodSquash},
   765  				DismissStaleReviewsOnPush:      true,
   766  				RequireCodeOwnerReview:         true,
   767  				RequireLastPushApproval:        true,
   768  				RequiredApprovingReviewCount:   1,
   769  				RequiredReviewThreadResolution: true,
   770  			},
   771  			RequiredStatusChecks: &RequiredStatusChecksRuleParameters{
   772  				DoNotEnforceOnCreate: Ptr(true),
   773  				RequiredStatusChecks: []*RuleStatusCheck{
   774  					{
   775  						Context:       "test",
   776  						IntegrationID: Ptr(int64(1)),
   777  					},
   778  				},
   779  				StrictRequiredStatusChecksPolicy: true,
   780  			},
   781  			NonFastForward: &EmptyRuleParameters{},
   782  			CommitMessagePattern: &PatternRuleParameters{
   783  				Name:     Ptr("avoid test commits"),
   784  				Negate:   Ptr(true),
   785  				Operator: "starts_with",
   786  				Pattern:  "[test]",
   787  			},
   788  			CommitAuthorEmailPattern: &PatternRuleParameters{
   789  				Operator: "contains",
   790  				Pattern:  "github",
   791  			},
   792  			CommitterEmailPattern: &PatternRuleParameters{
   793  				Name:     Ptr("avoid commit emails"),
   794  				Negate:   Ptr(true),
   795  				Operator: "ends_with",
   796  				Pattern:  "abc",
   797  			},
   798  			BranchNamePattern: &PatternRuleParameters{
   799  				Name:     Ptr("avoid branch names"),
   800  				Negate:   Ptr(true),
   801  				Operator: "regex",
   802  				Pattern:  "github$",
   803  			},
   804  			TagNamePattern: &PatternRuleParameters{
   805  				Name:     Ptr("avoid tag names"),
   806  				Negate:   Ptr(true),
   807  				Operator: "contains",
   808  				Pattern:  "github",
   809  			},
   810  			CodeScanning: &CodeScanningRuleParameters{
   811  				CodeScanningTools: []*RuleCodeScanningTool{
   812  					{
   813  						AlertsThreshold:         CodeScanningAlertsThresholdErrors,
   814  						SecurityAlertsThreshold: CodeScanningSecurityAlertsThresholdHighOrHigher,
   815  						Tool:                    "CodeQL",
   816  					},
   817  				},
   818  			},
   819  		},
   820  	}
   821  	if !cmp.Equal(ruleset, want) {
   822  		t.Errorf("Organizations.CreateRepositoryRuleset returned %+v, want %+v", ruleset, want)
   823  	}
   824  
   825  	const methodName = "CreateRepositoryRuleset"
   826  
   827  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   828  		got, resp, err := client.Organizations.CreateRepositoryRuleset(ctx, "o", RepositoryRuleset{})
   829  		if got != nil {
   830  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   831  		}
   832  		return resp, err
   833  	})
   834  }
   835  
   836  func TestOrganizationsService_CreateRepositoryRuleset_RepoIDs(t *testing.T) {
   837  	t.Parallel()
   838  	client, mux, _ := setup(t)
   839  
   840  	mux.HandleFunc("/orgs/o/rulesets", func(w http.ResponseWriter, r *http.Request) {
   841  		testMethod(t, r, "POST")
   842  		fmt.Fprint(w, `{
   843  			"id": 21,
   844  			"name": "ruleset",
   845  			"target": "branch",
   846  			"source_type": "Organization",
   847  			"source": "o",
   848  			"enforcement": "active",
   849  			"bypass_actors": [
   850  			  {
   851  				"actor_id": 234,
   852  				"actor_type": "Team"
   853  			  }
   854  			],
   855  			"conditions": {
   856  			  "ref_name": {
   857  				"include": [
   858  				  "refs/heads/main",
   859  				  "refs/heads/master"
   860  				],
   861  				"exclude": [
   862  				  "refs/heads/dev*"
   863  				]
   864  			  },
   865  			  "repository_id": {
   866  					"repository_ids": [ 123, 456 ]
   867  				}
   868  			},
   869  			"rules": [
   870  			  {
   871  				"type": "creation"
   872  			  },
   873  			  {
   874  				"type": "update",
   875  				"parameters": {
   876  				  "update_allows_fetch_and_merge": true
   877  				}
   878  			  },
   879  			  {
   880  				"type": "deletion"
   881  			  },
   882  			  {
   883  				"type": "required_linear_history"
   884  			  },
   885  			  {
   886  				"type": "required_deployments",
   887  				"parameters": {
   888  				  "required_deployment_environments": ["test"]
   889  				}
   890  			  },
   891  			  {
   892  				"type": "required_signatures"
   893  			  },
   894  			  {
   895  				"type": "pull_request",
   896  				"parameters": {
   897  					"allowed_merge_methods": ["rebase","squash"],
   898  				  "dismiss_stale_reviews_on_push": true,
   899  				  "require_code_owner_review": true,
   900  				  "require_last_push_approval": true,
   901  				  "required_approving_review_count": 1,
   902  				  "required_review_thread_resolution": true
   903  				}
   904  			  },
   905  			  {
   906  				"type": "required_status_checks",
   907  				"parameters": {
   908  					"do_not_enforce_on_create": true,
   909  				  "required_status_checks": [
   910  					{
   911  					  "context": "test",
   912  					  "integration_id": 1
   913  					}
   914  				  ],
   915  				  "strict_required_status_checks_policy": true
   916  				}
   917  			  },
   918  			  {
   919  				"type": "non_fast_forward"
   920  			  },
   921  			  {
   922  				"type": "commit_message_pattern",
   923  				"parameters": {
   924  				  "name": "avoid test commits",
   925  				  "negate": true,
   926  				  "operator": "starts_with",
   927  				  "pattern": "[test]"
   928  				}
   929  			  },
   930  			  {
   931  				"type": "commit_author_email_pattern",
   932  				"parameters": {
   933  				  "operator": "contains",
   934  				  "pattern": "github"
   935  				}
   936  			  },
   937  			  {
   938  				"type": "committer_email_pattern",
   939  				"parameters": {
   940  				  "name": "avoid commit emails",
   941  				  "negate": true,
   942  				  "operator": "ends_with",
   943  				  "pattern": "abc"
   944  				}
   945  			  },
   946  			  {
   947  				"type": "branch_name_pattern",
   948  				"parameters": {
   949  				  "name": "avoid branch names",
   950  				  "negate": true,
   951  				  "operator": "regex",
   952  				  "pattern": "github$"
   953  				}
   954  			  },
   955  			  {
   956  				"type": "tag_name_pattern",
   957  				"parameters": {
   958  				  "name": "avoid tag names",
   959  				  "negate": true,
   960  				  "operator": "contains",
   961  				  "pattern": "github"
   962  				}
   963  			  },
   964  			  {
   965  			    "type": "code_scanning",
   966  			    "parameters": {
   967  				  "code_scanning_tools": [
   968  				    {
   969  					  "tool": "CodeQL",
   970  					  "security_alerts_threshold": "high_or_higher",
   971  					  "alerts_threshold": "errors"
   972  				    }
   973  				  ]
   974  			    }
   975  			  }
   976  			]
   977  		  }`)
   978  	})
   979  
   980  	ctx := context.Background()
   981  	ruleset, _, err := client.Organizations.CreateRepositoryRuleset(ctx, "o", RepositoryRuleset{
   982  		Name:        "ruleset",
   983  		Target:      Ptr(RulesetTargetBranch),
   984  		Enforcement: "active",
   985  		BypassActors: []*BypassActor{
   986  			{
   987  				ActorID:   Ptr(int64(234)),
   988  				ActorType: Ptr(BypassActorTypeTeam),
   989  			},
   990  		},
   991  		Conditions: &RepositoryRulesetConditions{
   992  			RefName: &RepositoryRulesetRefConditionParameters{
   993  				Include: []string{"refs/heads/main", "refs/heads/master"},
   994  				Exclude: []string{"refs/heads/dev*"},
   995  			},
   996  			RepositoryID: &RepositoryRulesetRepositoryIDsConditionParameters{
   997  				RepositoryIDs: []int64{123, 456},
   998  			},
   999  		},
  1000  		Rules: &RepositoryRulesetRules{
  1001  			Creation: &EmptyRuleParameters{},
  1002  			Update: &UpdateRuleParameters{
  1003  				UpdateAllowsFetchAndMerge: true,
  1004  			},
  1005  			Deletion:              &EmptyRuleParameters{},
  1006  			RequiredLinearHistory: &EmptyRuleParameters{},
  1007  			RequiredDeployments: &RequiredDeploymentsRuleParameters{
  1008  				RequiredDeploymentEnvironments: []string{"test"},
  1009  			},
  1010  			RequiredSignatures: &EmptyRuleParameters{},
  1011  			PullRequest: &PullRequestRuleParameters{
  1012  				AllowedMergeMethods:            []PullRequestMergeMethod{PullRequestMergeMethodRebase, PullRequestMergeMethodSquash},
  1013  				DismissStaleReviewsOnPush:      true,
  1014  				RequireCodeOwnerReview:         true,
  1015  				RequireLastPushApproval:        true,
  1016  				RequiredApprovingReviewCount:   1,
  1017  				RequiredReviewThreadResolution: true,
  1018  			},
  1019  			RequiredStatusChecks: &RequiredStatusChecksRuleParameters{
  1020  				DoNotEnforceOnCreate: Ptr(true),
  1021  				RequiredStatusChecks: []*RuleStatusCheck{
  1022  					{
  1023  						Context:       "test",
  1024  						IntegrationID: Ptr(int64(1)),
  1025  					},
  1026  				},
  1027  				StrictRequiredStatusChecksPolicy: true,
  1028  			},
  1029  			NonFastForward: &EmptyRuleParameters{},
  1030  			CommitMessagePattern: &PatternRuleParameters{
  1031  				Name:     Ptr("avoid test commits"),
  1032  				Negate:   Ptr(true),
  1033  				Operator: "starts_with",
  1034  				Pattern:  "[test]",
  1035  			},
  1036  			CommitAuthorEmailPattern: &PatternRuleParameters{
  1037  				Operator: "contains",
  1038  				Pattern:  "github",
  1039  			},
  1040  			CommitterEmailPattern: &PatternRuleParameters{
  1041  				Name:     Ptr("avoid commit emails"),
  1042  				Negate:   Ptr(true),
  1043  				Operator: "ends_with",
  1044  				Pattern:  "abc",
  1045  			},
  1046  			BranchNamePattern: &PatternRuleParameters{
  1047  				Name:     Ptr("avoid branch names"),
  1048  				Negate:   Ptr(true),
  1049  				Operator: "regex",
  1050  				Pattern:  "github$",
  1051  			},
  1052  			TagNamePattern: &PatternRuleParameters{
  1053  				Name:     Ptr("avoid tag names"),
  1054  				Negate:   Ptr(true),
  1055  				Operator: "contains",
  1056  				Pattern:  "github",
  1057  			},
  1058  			CodeScanning: &CodeScanningRuleParameters{
  1059  				CodeScanningTools: []*RuleCodeScanningTool{
  1060  					{
  1061  						AlertsThreshold:         CodeScanningAlertsThresholdErrors,
  1062  						SecurityAlertsThreshold: CodeScanningSecurityAlertsThresholdHighOrHigher,
  1063  						Tool:                    "CodeQL",
  1064  					},
  1065  				},
  1066  			},
  1067  		},
  1068  	})
  1069  	if err != nil {
  1070  		t.Errorf("Organizations.CreateRepositoryRuleset returned error: %v", err)
  1071  	}
  1072  
  1073  	want := &RepositoryRuleset{
  1074  		ID:          Ptr(int64(21)),
  1075  		Name:        "ruleset",
  1076  		Target:      Ptr(RulesetTargetBranch),
  1077  		SourceType:  Ptr(RulesetSourceTypeOrganization),
  1078  		Source:      "o",
  1079  		Enforcement: "active",
  1080  		BypassActors: []*BypassActor{
  1081  			{
  1082  				ActorID:   Ptr(int64(234)),
  1083  				ActorType: Ptr(BypassActorTypeTeam),
  1084  			},
  1085  		},
  1086  		Conditions: &RepositoryRulesetConditions{
  1087  			RefName: &RepositoryRulesetRefConditionParameters{
  1088  				Include: []string{"refs/heads/main", "refs/heads/master"},
  1089  				Exclude: []string{"refs/heads/dev*"},
  1090  			},
  1091  			RepositoryID: &RepositoryRulesetRepositoryIDsConditionParameters{
  1092  				RepositoryIDs: []int64{123, 456},
  1093  			},
  1094  		},
  1095  		Rules: &RepositoryRulesetRules{
  1096  			Creation: &EmptyRuleParameters{},
  1097  			Update: &UpdateRuleParameters{
  1098  				UpdateAllowsFetchAndMerge: true,
  1099  			},
  1100  			Deletion:              &EmptyRuleParameters{},
  1101  			RequiredLinearHistory: &EmptyRuleParameters{},
  1102  			RequiredDeployments: &RequiredDeploymentsRuleParameters{
  1103  				RequiredDeploymentEnvironments: []string{"test"},
  1104  			},
  1105  			RequiredSignatures: &EmptyRuleParameters{},
  1106  			PullRequest: &PullRequestRuleParameters{
  1107  				AllowedMergeMethods:            []PullRequestMergeMethod{PullRequestMergeMethodRebase, PullRequestMergeMethodSquash},
  1108  				DismissStaleReviewsOnPush:      true,
  1109  				RequireCodeOwnerReview:         true,
  1110  				RequireLastPushApproval:        true,
  1111  				RequiredApprovingReviewCount:   1,
  1112  				RequiredReviewThreadResolution: true,
  1113  			},
  1114  			RequiredStatusChecks: &RequiredStatusChecksRuleParameters{
  1115  				DoNotEnforceOnCreate: Ptr(true),
  1116  				RequiredStatusChecks: []*RuleStatusCheck{
  1117  					{
  1118  						Context:       "test",
  1119  						IntegrationID: Ptr(int64(1)),
  1120  					},
  1121  				},
  1122  				StrictRequiredStatusChecksPolicy: true,
  1123  			},
  1124  			NonFastForward: &EmptyRuleParameters{},
  1125  			CommitMessagePattern: &PatternRuleParameters{
  1126  				Name:     Ptr("avoid test commits"),
  1127  				Negate:   Ptr(true),
  1128  				Operator: "starts_with",
  1129  				Pattern:  "[test]",
  1130  			},
  1131  			CommitAuthorEmailPattern: &PatternRuleParameters{
  1132  				Operator: "contains",
  1133  				Pattern:  "github",
  1134  			},
  1135  			CommitterEmailPattern: &PatternRuleParameters{
  1136  				Name:     Ptr("avoid commit emails"),
  1137  				Negate:   Ptr(true),
  1138  				Operator: "ends_with",
  1139  				Pattern:  "abc",
  1140  			},
  1141  			BranchNamePattern: &PatternRuleParameters{
  1142  				Name:     Ptr("avoid branch names"),
  1143  				Negate:   Ptr(true),
  1144  				Operator: "regex",
  1145  				Pattern:  "github$",
  1146  			},
  1147  			TagNamePattern: &PatternRuleParameters{
  1148  				Name:     Ptr("avoid tag names"),
  1149  				Negate:   Ptr(true),
  1150  				Operator: "contains",
  1151  				Pattern:  "github",
  1152  			},
  1153  			CodeScanning: &CodeScanningRuleParameters{
  1154  				CodeScanningTools: []*RuleCodeScanningTool{
  1155  					{
  1156  						AlertsThreshold:         CodeScanningAlertsThresholdErrors,
  1157  						SecurityAlertsThreshold: CodeScanningSecurityAlertsThresholdHighOrHigher,
  1158  						Tool:                    "CodeQL",
  1159  					},
  1160  				},
  1161  			},
  1162  		},
  1163  	}
  1164  	if !cmp.Equal(ruleset, want) {
  1165  		t.Errorf("Organizations.CreateRepositoryRuleset returned %+v, want %+v", ruleset, want)
  1166  	}
  1167  
  1168  	const methodName = "CreateRepositoryRuleset"
  1169  
  1170  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
  1171  		got, resp, err := client.Organizations.CreateRepositoryRuleset(ctx, "o", RepositoryRuleset{})
  1172  		if got != nil {
  1173  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
  1174  		}
  1175  		return resp, err
  1176  	})
  1177  }
  1178  
  1179  func TestOrganizationsService_GetRepositoryRuleset(t *testing.T) {
  1180  	t.Parallel()
  1181  	client, mux, _ := setup(t)
  1182  
  1183  	mux.HandleFunc("/orgs/o/rulesets/21", func(w http.ResponseWriter, r *http.Request) {
  1184  		testMethod(t, r, "GET")
  1185  		fmt.Fprint(w, `{
  1186  			"id": 21,
  1187  			"name": "test ruleset",
  1188  			"target": "branch",
  1189  			"source_type": "Organization",
  1190  			"source": "o",
  1191  			"enforcement": "active",
  1192  			"bypass_mode": "none",
  1193  			"node_id": "nid",
  1194  			"_links": {
  1195  			  "self": {
  1196  				"href": "https://api.github.com/orgs/o/rulesets/21"
  1197  			  }
  1198  			},
  1199  			"conditions": {
  1200  				"ref_name": {
  1201  				  "include": [
  1202  					"refs/heads/main",
  1203  					"refs/heads/master"
  1204  				  ],
  1205  				  "exclude": [
  1206  					"refs/heads/dev*"
  1207  				  ]
  1208  				},
  1209  				"repository_name": {
  1210  				  "include": [
  1211  					"important_repository",
  1212  					"another_important_repository"
  1213  				  ],
  1214  				  "exclude": [
  1215  					"unimportant_repository"
  1216  				  ],
  1217  				  "protected": true
  1218  				}
  1219  			  },
  1220  			  "rules": [
  1221  				{
  1222  				  "type": "creation"
  1223  				}
  1224  			  ]
  1225  		}`)
  1226  	})
  1227  
  1228  	ctx := context.Background()
  1229  	rulesets, _, err := client.Organizations.GetRepositoryRuleset(ctx, "o", 21)
  1230  	if err != nil {
  1231  		t.Errorf("Organizations.GetOrganizationRepositoryRuleset returned error: %v", err)
  1232  	}
  1233  
  1234  	want := &RepositoryRuleset{
  1235  		ID:          Ptr(int64(21)),
  1236  		Name:        "test ruleset",
  1237  		Target:      Ptr(RulesetTargetBranch),
  1238  		SourceType:  Ptr(RulesetSourceTypeOrganization),
  1239  		Source:      "o",
  1240  		Enforcement: "active",
  1241  		NodeID:      Ptr("nid"),
  1242  		Links: &RepositoryRulesetLinks{
  1243  			Self: &RepositoryRulesetLink{HRef: Ptr("https://api.github.com/orgs/o/rulesets/21")},
  1244  		},
  1245  		Conditions: &RepositoryRulesetConditions{
  1246  			RefName: &RepositoryRulesetRefConditionParameters{
  1247  				Include: []string{"refs/heads/main", "refs/heads/master"},
  1248  				Exclude: []string{"refs/heads/dev*"},
  1249  			},
  1250  			RepositoryName: &RepositoryRulesetRepositoryNamesConditionParameters{
  1251  				Include:   []string{"important_repository", "another_important_repository"},
  1252  				Exclude:   []string{"unimportant_repository"},
  1253  				Protected: Ptr(true),
  1254  			},
  1255  		},
  1256  		Rules: &RepositoryRulesetRules{Creation: &EmptyRuleParameters{}},
  1257  	}
  1258  	if !cmp.Equal(rulesets, want) {
  1259  		t.Errorf("Organizations.GetRepositoryRuleset returned %+v, want %+v", rulesets, want)
  1260  	}
  1261  
  1262  	const methodName = "GetRepositoryRuleset"
  1263  
  1264  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
  1265  		got, resp, err := client.Organizations.GetRepositoryRuleset(ctx, "o", 21)
  1266  		if got != nil {
  1267  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
  1268  		}
  1269  		return resp, err
  1270  	})
  1271  }
  1272  
  1273  func TestOrganizationsService_GetRepositoryRulesetWithRepoPropCondition(t *testing.T) {
  1274  	t.Parallel()
  1275  	client, mux, _ := setup(t)
  1276  
  1277  	mux.HandleFunc("/orgs/o/rulesets/21", func(w http.ResponseWriter, r *http.Request) {
  1278  		testMethod(t, r, "GET")
  1279  		fmt.Fprint(w, `{
  1280  			"id": 21,
  1281  			"name": "test ruleset",
  1282  			"target": "branch",
  1283  			"source_type": "Organization",
  1284  			"source": "o",
  1285  			"enforcement": "active",
  1286  			"bypass_mode": "none",
  1287  			"node_id": "nid",
  1288  			"_links": {
  1289  			  "self": {
  1290  				"href": "https://api.github.com/orgs/o/rulesets/21"
  1291  			  }
  1292  			},
  1293  			"conditions": {
  1294  			  "repository_property": {
  1295  				"exclude": [],
  1296  				"include": [
  1297  				  {
  1298  					"name": "testIncludeProp",
  1299  					"source": "custom",
  1300  					"property_values": [
  1301  					  "true"
  1302  					]
  1303  				  }
  1304  				]
  1305  			  }
  1306  			},
  1307  			"rules": [
  1308  			{
  1309  				"type": "creation"
  1310  			}
  1311  			]
  1312  		}`)
  1313  	})
  1314  
  1315  	ctx := context.Background()
  1316  	rulesets, _, err := client.Organizations.GetRepositoryRuleset(ctx, "o", 21)
  1317  	if err != nil {
  1318  		t.Errorf("Organizations.GetOrganizationRepositoryRuleset returned error: %v", err)
  1319  	}
  1320  
  1321  	want := &RepositoryRuleset{
  1322  		ID:          Ptr(int64(21)),
  1323  		Name:        "test ruleset",
  1324  		Target:      Ptr(RulesetTargetBranch),
  1325  		SourceType:  Ptr(RulesetSourceTypeOrganization),
  1326  		Source:      "o",
  1327  		Enforcement: "active",
  1328  		NodeID:      Ptr("nid"),
  1329  		Links: &RepositoryRulesetLinks{
  1330  			Self: &RepositoryRulesetLink{HRef: Ptr("https://api.github.com/orgs/o/rulesets/21")},
  1331  		},
  1332  		Conditions: &RepositoryRulesetConditions{
  1333  			RepositoryProperty: &RepositoryRulesetRepositoryPropertyConditionParameters{
  1334  				Include: []*RepositoryRulesetRepositoryPropertyTargetParameters{
  1335  					{
  1336  						Name:           "testIncludeProp",
  1337  						Source:         Ptr("custom"),
  1338  						PropertyValues: []string{"true"},
  1339  					},
  1340  				},
  1341  				Exclude: []*RepositoryRulesetRepositoryPropertyTargetParameters{},
  1342  			},
  1343  		},
  1344  		Rules: &RepositoryRulesetRules{Creation: &EmptyRuleParameters{}},
  1345  	}
  1346  	if !cmp.Equal(rulesets, want) {
  1347  		t.Errorf("Organizations.GetRepositoryRuleset returned %+v, want %+v", rulesets, want)
  1348  	}
  1349  
  1350  	const methodName = "GetRepositoryRuleset"
  1351  
  1352  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
  1353  		got, resp, err := client.Organizations.GetRepositoryRuleset(ctx, "o", 21)
  1354  		if got != nil {
  1355  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
  1356  		}
  1357  		return resp, err
  1358  	})
  1359  }
  1360  
  1361  func TestOrganizationsService_UpdateRepositoryRuleset(t *testing.T) {
  1362  	t.Parallel()
  1363  	client, mux, _ := setup(t)
  1364  
  1365  	mux.HandleFunc("/orgs/o/rulesets/21", func(w http.ResponseWriter, r *http.Request) {
  1366  		testMethod(t, r, "PUT")
  1367  		fmt.Fprint(w, `{
  1368  			"id": 21,
  1369  			"name": "test ruleset",
  1370  			"target": "branch",
  1371  			"source_type": "Organization",
  1372  			"source": "o",
  1373  			"enforcement": "active",
  1374  			"bypass_mode": "none",
  1375  			"node_id": "nid",
  1376  			"_links": {
  1377  			  "self": {
  1378  				"href": "https://api.github.com/orgs/o/rulesets/21"
  1379  			  }
  1380  			},
  1381  			"conditions": {
  1382  				"ref_name": {
  1383  				  "include": [
  1384  					"refs/heads/main",
  1385  					"refs/heads/master"
  1386  				  ],
  1387  				  "exclude": [
  1388  					"refs/heads/dev*"
  1389  				  ]
  1390  				},
  1391  				"repository_name": {
  1392  				  "include": [
  1393  					"important_repository",
  1394  					"another_important_repository"
  1395  				  ],
  1396  				  "exclude": [
  1397  					"unimportant_repository"
  1398  				  ],
  1399  				  "protected": true
  1400  				}
  1401  			  },
  1402  			  "rules": [
  1403  				{
  1404  				  "type": "creation"
  1405  				}
  1406  			  ]
  1407  		}`)
  1408  	})
  1409  
  1410  	ctx := context.Background()
  1411  	rulesets, _, err := client.Organizations.UpdateRepositoryRuleset(ctx, "o", 21, RepositoryRuleset{
  1412  		Name:        "test ruleset",
  1413  		Target:      Ptr(RulesetTargetBranch),
  1414  		Enforcement: "active",
  1415  		Conditions: &RepositoryRulesetConditions{
  1416  			RefName: &RepositoryRulesetRefConditionParameters{
  1417  				Include: []string{"refs/heads/main", "refs/heads/master"},
  1418  				Exclude: []string{"refs/heads/dev*"},
  1419  			},
  1420  			RepositoryName: &RepositoryRulesetRepositoryNamesConditionParameters{
  1421  				Include:   []string{"important_repository", "another_important_repository"},
  1422  				Exclude:   []string{"unimportant_repository"},
  1423  				Protected: Ptr(true),
  1424  			},
  1425  		},
  1426  		Rules: &RepositoryRulesetRules{Creation: &EmptyRuleParameters{}},
  1427  	})
  1428  	if err != nil {
  1429  		t.Errorf("Organizations.UpdateRepositoryRuleset returned error: %v", err)
  1430  	}
  1431  
  1432  	want := &RepositoryRuleset{
  1433  		ID:          Ptr(int64(21)),
  1434  		Name:        "test ruleset",
  1435  		Target:      Ptr(RulesetTargetBranch),
  1436  		SourceType:  Ptr(RulesetSourceTypeOrganization),
  1437  		Source:      "o",
  1438  		Enforcement: "active",
  1439  		NodeID:      Ptr("nid"),
  1440  		Links: &RepositoryRulesetLinks{
  1441  			Self: &RepositoryRulesetLink{HRef: Ptr("https://api.github.com/orgs/o/rulesets/21")},
  1442  		},
  1443  		Conditions: &RepositoryRulesetConditions{
  1444  			RefName: &RepositoryRulesetRefConditionParameters{
  1445  				Include: []string{"refs/heads/main", "refs/heads/master"},
  1446  				Exclude: []string{"refs/heads/dev*"},
  1447  			},
  1448  			RepositoryName: &RepositoryRulesetRepositoryNamesConditionParameters{
  1449  				Include:   []string{"important_repository", "another_important_repository"},
  1450  				Exclude:   []string{"unimportant_repository"},
  1451  				Protected: Ptr(true),
  1452  			},
  1453  		},
  1454  		Rules: &RepositoryRulesetRules{Creation: &EmptyRuleParameters{}},
  1455  	}
  1456  	if !cmp.Equal(rulesets, want) {
  1457  		t.Errorf("Organizations.UpdateRepositoryRuleset returned %+v, want %+v", rulesets, want)
  1458  	}
  1459  
  1460  	const methodName = "UpdateRepositoryRuleset"
  1461  
  1462  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
  1463  		got, resp, err := client.Organizations.UpdateRepositoryRuleset(ctx, "o", 21, RepositoryRuleset{})
  1464  		if got != nil {
  1465  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
  1466  		}
  1467  		return resp, err
  1468  	})
  1469  }
  1470  
  1471  func TestOrganizationsService_UpdateRepositoryRulesetWithRepoProp(t *testing.T) {
  1472  	t.Parallel()
  1473  	client, mux, _ := setup(t)
  1474  
  1475  	mux.HandleFunc("/orgs/o/rulesets/21", func(w http.ResponseWriter, r *http.Request) {
  1476  		testMethod(t, r, "PUT")
  1477  		fmt.Fprint(w, `{
  1478  			"id": 21,
  1479  			"name": "test ruleset",
  1480  			"target": "branch",
  1481  			"source_type": "Organization",
  1482  			"source": "o",
  1483  			"enforcement": "active",
  1484  			"bypass_mode": "none",
  1485  			"node_id": "nid",
  1486  			"_links": {
  1487  			  "self": {
  1488  				"href": "https://api.github.com/orgs/o/rulesets/21"
  1489  			  }
  1490  			},
  1491  			"conditions": {
  1492  			  "repository_property": {
  1493  				"exclude": [],
  1494  				"include": [
  1495  				  {
  1496  					"name": "testIncludeProp",
  1497  					"source": "custom",
  1498  					"property_values": [
  1499  					  "true"
  1500  					]
  1501  				  }
  1502  				]
  1503  			  }
  1504  			  },
  1505  			  "rules": [
  1506  				{
  1507  				  "type": "creation"
  1508  				}
  1509  			  ]
  1510  		}`)
  1511  	})
  1512  
  1513  	ctx := context.Background()
  1514  	rulesets, _, err := client.Organizations.UpdateRepositoryRuleset(ctx, "o", 21, RepositoryRuleset{
  1515  		Name:        "test ruleset",
  1516  		Target:      Ptr(RulesetTargetBranch),
  1517  		Enforcement: "active",
  1518  		Conditions: &RepositoryRulesetConditions{
  1519  			RepositoryProperty: &RepositoryRulesetRepositoryPropertyConditionParameters{
  1520  				Include: []*RepositoryRulesetRepositoryPropertyTargetParameters{
  1521  					{
  1522  						Name:           "testIncludeProp",
  1523  						Source:         Ptr("custom"),
  1524  						PropertyValues: []string{"true"},
  1525  					},
  1526  				},
  1527  				Exclude: []*RepositoryRulesetRepositoryPropertyTargetParameters{},
  1528  			},
  1529  		},
  1530  		Rules: &RepositoryRulesetRules{Creation: &EmptyRuleParameters{}},
  1531  	})
  1532  	if err != nil {
  1533  		t.Errorf("Organizations.UpdateRepositoryRuleset returned error: %v", err)
  1534  	}
  1535  
  1536  	want := &RepositoryRuleset{
  1537  		ID:          Ptr(int64(21)),
  1538  		Name:        "test ruleset",
  1539  		Target:      Ptr(RulesetTargetBranch),
  1540  		SourceType:  Ptr(RulesetSourceTypeOrganization),
  1541  		Source:      "o",
  1542  		Enforcement: "active",
  1543  		NodeID:      Ptr("nid"),
  1544  		Links: &RepositoryRulesetLinks{
  1545  			Self: &RepositoryRulesetLink{HRef: Ptr("https://api.github.com/orgs/o/rulesets/21")},
  1546  		},
  1547  		Conditions: &RepositoryRulesetConditions{
  1548  			RepositoryProperty: &RepositoryRulesetRepositoryPropertyConditionParameters{
  1549  				Include: []*RepositoryRulesetRepositoryPropertyTargetParameters{
  1550  					{
  1551  						Name:           "testIncludeProp",
  1552  						Source:         Ptr("custom"),
  1553  						PropertyValues: []string{"true"},
  1554  					},
  1555  				},
  1556  				Exclude: []*RepositoryRulesetRepositoryPropertyTargetParameters{},
  1557  			},
  1558  		},
  1559  		Rules: &RepositoryRulesetRules{Creation: &EmptyRuleParameters{}},
  1560  	}
  1561  	if !cmp.Equal(rulesets, want) {
  1562  		t.Errorf("Organizations.UpdateRepositoryRuleset returned %+v, want %+v", rulesets, want)
  1563  	}
  1564  
  1565  	const methodName = "UpdateRepositoryRuleset"
  1566  
  1567  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
  1568  		got, resp, err := client.Organizations.UpdateRepositoryRuleset(ctx, "o", 21, RepositoryRuleset{})
  1569  		if got != nil {
  1570  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
  1571  		}
  1572  		return resp, err
  1573  	})
  1574  }
  1575  
  1576  func TestOrganizationsService_UpdateRepositoryRulesetClearBypassActor(t *testing.T) {
  1577  	t.Parallel()
  1578  	client, mux, _ := setup(t)
  1579  
  1580  	mux.HandleFunc("/orgs/o/rulesets/21", func(w http.ResponseWriter, r *http.Request) {
  1581  		testMethod(t, r, "PUT")
  1582  		fmt.Fprint(w, `{
  1583  			"id": 21,
  1584  			"name": "test ruleset",
  1585  			"target": "branch",
  1586  			"source_type": "Organization",
  1587  			"source": "o",
  1588  			"enforcement": "active",
  1589  			"bypass_mode": "none",
  1590  			"conditions": {
  1591  				"repository_name": {
  1592  					"include": [
  1593  						"important_repository",
  1594  						"another_important_repository"
  1595  					],
  1596  					"exclude": [
  1597  						"unimportant_repository"
  1598  					],
  1599  					"protected": true
  1600  				},
  1601  			  "ref_name": {
  1602  					"include": [
  1603  						"refs/heads/main",
  1604  						"refs/heads/master"
  1605  					],
  1606  					"exclude": [
  1607  						"refs/heads/dev*"
  1608  					]
  1609  				}
  1610  			},
  1611  			"rules": [
  1612  			  {
  1613  					"type": "creation"
  1614  			  }
  1615  			]
  1616  		}`)
  1617  	})
  1618  
  1619  	ctx := context.Background()
  1620  
  1621  	_, err := client.Organizations.UpdateRepositoryRulesetClearBypassActor(ctx, "o", 21)
  1622  	if err != nil {
  1623  		t.Errorf("Organizations.UpdateRepositoryRulesetClearBypassActor returned error: %v \n", err)
  1624  	}
  1625  
  1626  	const methodName = "UpdateRepositoryRulesetClearBypassActor"
  1627  
  1628  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
  1629  		return client.Organizations.UpdateRepositoryRulesetClearBypassActor(ctx, "o", 21)
  1630  	})
  1631  }
  1632  
  1633  func TestOrganizationsService_DeleteRepositoryRuleset(t *testing.T) {
  1634  	t.Parallel()
  1635  	client, mux, _ := setup(t)
  1636  
  1637  	mux.HandleFunc("/orgs/o/rulesets/21", func(_ http.ResponseWriter, r *http.Request) {
  1638  		testMethod(t, r, "DELETE")
  1639  	})
  1640  
  1641  	ctx := context.Background()
  1642  	_, err := client.Organizations.DeleteRepositoryRuleset(ctx, "o", 21)
  1643  	if err != nil {
  1644  		t.Errorf("Organizations.DeleteRepositoryRuleset returned error: %v", err)
  1645  	}
  1646  
  1647  	const methodName = "DeleteRepositoryRuleset"
  1648  
  1649  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
  1650  		return client.Organizations.DeleteRepositoryRuleset(ctx, "0", 21)
  1651  	})
  1652  }