github.com/google/go-github/v53@v53.2.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_GetAllOrganizationRulesets(t *testing.T) {
    18  	client, mux, _, teardown := setup()
    19  	defer teardown()
    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": 26110,
    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/26110"
    35  			  }
    36  			}
    37  		}]`)
    38  	})
    39  
    40  	ctx := context.Background()
    41  	rulesets, _, err := client.Organizations.GetAllOrganizationRulesets(ctx, "o")
    42  	if err != nil {
    43  		t.Errorf("Organizations.GetAllOrganizationRulesets returned error: %v", err)
    44  	}
    45  
    46  	want := []*Ruleset{{
    47  		ID:          26110,
    48  		Name:        "test ruleset",
    49  		Target:      String("branch"),
    50  		SourceType:  String("Organization"),
    51  		Source:      "o",
    52  		Enforcement: "active",
    53  		BypassMode:  String("none"),
    54  		NodeID:      String("nid"),
    55  		Links: &RulesetLinks{
    56  			Self: &RulesetLink{HRef: String("https://api.github.com/orgs/o/rulesets/26110")},
    57  		},
    58  	}}
    59  	if !cmp.Equal(rulesets, want) {
    60  		t.Errorf("Organizations.GetAllOrganizationRulesets returned %+v, want %+v", rulesets, want)
    61  	}
    62  
    63  	const methodName = "GetAllOrganizationRulesets"
    64  
    65  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
    66  		got, resp, err := client.Organizations.GetAllOrganizationRulesets(ctx, "o")
    67  		if got != nil {
    68  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
    69  		}
    70  		return resp, err
    71  	})
    72  }
    73  
    74  func TestOrganizationsService_CreateOrganizationRuleset(t *testing.T) {
    75  	client, mux, _, teardown := setup()
    76  	defer teardown()
    77  
    78  	mux.HandleFunc("/orgs/o/rulesets", func(w http.ResponseWriter, r *http.Request) {
    79  		testMethod(t, r, "POST")
    80  		fmt.Fprint(w, `{
    81  			"id": 21,
    82  			"name": "ruleset",
    83  			"target": "branch",
    84  			"source_type": "Organization",
    85  			"source": "o",
    86  			"enforcement": "active",
    87  			"bypass_actors": [
    88  			  {
    89  				"actor_id": 234,
    90  				"actor_type": "Team"
    91  			  }
    92  			],
    93  			"conditions": {
    94  			  "ref_name": {
    95  				"include": [
    96  				  "refs/heads/main",
    97  				  "refs/heads/master"
    98  				],
    99  				"exclude": [
   100  				  "refs/heads/dev*"
   101  				]
   102  			  },
   103  			  "repository_name": {
   104  				"include": [
   105  				  "important_repository",
   106  				  "another_important_repository"
   107  				],
   108  				"exclude": [
   109  				  "unimportant_repository"
   110  				],
   111  				"protected": true
   112  			  }
   113  			},
   114  			"rules": [
   115  			  {
   116  				"type": "creation"
   117  			  },
   118  			  {
   119  				"type": "update",
   120  				"parameters": {
   121  				  "update_allows_fetch_and_merge": true
   122  				}
   123  			  },
   124  			  {
   125  				"type": "deletion"
   126  			  },
   127  			  {
   128  				"type": "required_linear_history"
   129  			  },
   130  			  {
   131  				"type": "required_deployments",
   132  				"parameters": {
   133  				  "required_deployment_environments": ["test"]
   134  				}
   135  			  },
   136  			  {
   137  				"type": "required_signatures"
   138  			  },
   139  			  {
   140  				"type": "pull_request",
   141  				"parameters": {
   142  				  "dismiss_stale_reviews_on_push": true,
   143  				  "require_code_owner_review": true,
   144  				  "require_last_push_approval": true,
   145  				  "required_approving_review_count": 1,
   146  				  "required_review_thread_resolution": true
   147  				}
   148  			  },
   149  			  {
   150  				"type": "required_status_checks",
   151  				"parameters": {
   152  				  "required_status_checks": [
   153  					{
   154  					  "context": "test",
   155  					  "integration_id": 1
   156  					}
   157  				  ],
   158  				  "strict_required_status_checks_policy": true
   159  				}
   160  			  },
   161  			  {
   162  				"type": "non_fast_forward"
   163  			  },
   164  			  {
   165  				"type": "commit_message_pattern",
   166  				"parameters": {
   167  				  "name": "avoid test commits",
   168  				  "negate": true,
   169  				  "operator": "starts_with",
   170  				  "pattern": "[test]"
   171  				}
   172  			  },
   173  			  {
   174  				"type": "commit_author_email_pattern",
   175  				"parameters": {
   176  				  "operator": "contains",
   177  				  "pattern": "github"
   178  				}
   179  			  },
   180  			  {
   181  				"type": "committer_email_pattern",
   182  				"parameters": {
   183  				  "name": "avoid commit emails",
   184  				  "negate": true,
   185  				  "operator": "ends_with",
   186  				  "pattern": "abc"
   187  				}
   188  			  },
   189  			  {
   190  				"type": "branch_name_pattern",
   191  				"parameters": {
   192  				  "name": "avoid branch names",
   193  				  "negate": true,
   194  				  "operator": "regex",
   195  				  "pattern": "github$"
   196  				}
   197  			  },
   198  			  {
   199  				"type": "tag_name_pattern",
   200  				"parameters": {
   201  				  "name": "avoid tag names",
   202  				  "negate": true,
   203  				  "operator": "contains",
   204  				  "pattern": "github"
   205  				}
   206  			  }
   207  			]
   208  		  }`)
   209  	})
   210  
   211  	ctx := context.Background()
   212  	ruleset, _, err := client.Organizations.CreateOrganizationRuleset(ctx, "o", &Ruleset{
   213  		ID:          21,
   214  		Name:        "ruleset",
   215  		Target:      String("branch"),
   216  		SourceType:  String("Organization"),
   217  		Source:      "o",
   218  		Enforcement: "active",
   219  		BypassActors: []*BypassActor{
   220  			{
   221  				ActorID:   Int64(234),
   222  				ActorType: String("Team"),
   223  			},
   224  		},
   225  		Conditions: &RulesetConditions{
   226  			RefName: &RulesetRefConditionParameters{
   227  				Include: []string{"refs/heads/main", "refs/heads/master"},
   228  				Exclude: []string{"refs/heads/dev*"},
   229  			},
   230  			RepositoryName: &RulesetRepositoryConditionParameters{
   231  				Include:   []string{"important_repository", "another_important_repository"},
   232  				Exclude:   []string{"unimportant_repository"},
   233  				Protected: Bool(true),
   234  			},
   235  		},
   236  		Rules: []*RepositoryRule{
   237  			NewCreationRule(),
   238  			NewUpdateRule(&UpdateAllowsFetchAndMergeRuleParameters{
   239  				UpdateAllowsFetchAndMerge: true,
   240  			}),
   241  			NewDeletionRule(),
   242  			NewRequiredLinearHistoryRule(),
   243  			NewRequiredDeploymentsRule(&RequiredDeploymentEnvironmentsRuleParameters{
   244  				RequiredDeploymentEnvironments: []string{"test"},
   245  			}),
   246  			NewRequiredSignaturesRule(),
   247  			NewPullRequestRule(&PullRequestRuleParameters{
   248  				RequireCodeOwnerReview:         true,
   249  				RequireLastPushApproval:        true,
   250  				RequiredApprovingReviewCount:   1,
   251  				RequiredReviewThreadResolution: true,
   252  				DismissStaleReviewsOnPush:      true,
   253  			}),
   254  			NewRequiredStatusChecksRule(&RequiredStatusChecksRuleParameters{
   255  				RequiredStatusChecks: []RuleRequiredStatusChecks{
   256  					{
   257  						Context:       "test",
   258  						IntegrationID: Int64(1),
   259  					},
   260  				},
   261  				StrictRequiredStatusChecksPolicy: true,
   262  			}),
   263  			NewNonFastForwardRule(),
   264  			NewCommitMessagePatternRule(&RulePatternParameters{
   265  				Name:     String("avoid test commits"),
   266  				Negate:   Bool(true),
   267  				Operator: "starts_with",
   268  				Pattern:  "[test]",
   269  			}),
   270  			NewCommitAuthorEmailPatternRule(&RulePatternParameters{
   271  				Operator: "contains",
   272  				Pattern:  "github",
   273  			}),
   274  			NewCommitterEmailPatternRule(&RulePatternParameters{
   275  				Name:     String("avoid commit emails"),
   276  				Negate:   Bool(true),
   277  				Operator: "ends_with",
   278  				Pattern:  "abc",
   279  			}),
   280  			NewBranchNamePatternRule(&RulePatternParameters{
   281  				Name:     String("avoid branch names"),
   282  				Negate:   Bool(true),
   283  				Operator: "regex",
   284  				Pattern:  "github$",
   285  			}),
   286  			NewTagNamePatternRule(&RulePatternParameters{
   287  				Name:     String("avoid tag names"),
   288  				Negate:   Bool(true),
   289  				Operator: "contains",
   290  				Pattern:  "github",
   291  			}),
   292  		},
   293  	})
   294  	if err != nil {
   295  		t.Errorf("Organizations.CreateOrganizationRuleset returned error: %v", err)
   296  	}
   297  
   298  	want := &Ruleset{
   299  		ID:          21,
   300  		Name:        "ruleset",
   301  		Target:      String("branch"),
   302  		SourceType:  String("Organization"),
   303  		Source:      "o",
   304  		Enforcement: "active",
   305  		BypassActors: []*BypassActor{
   306  			{
   307  				ActorID:   Int64(234),
   308  				ActorType: String("Team"),
   309  			},
   310  		},
   311  		Conditions: &RulesetConditions{
   312  			RefName: &RulesetRefConditionParameters{
   313  				Include: []string{"refs/heads/main", "refs/heads/master"},
   314  				Exclude: []string{"refs/heads/dev*"},
   315  			},
   316  			RepositoryName: &RulesetRepositoryConditionParameters{
   317  				Include:   []string{"important_repository", "another_important_repository"},
   318  				Exclude:   []string{"unimportant_repository"},
   319  				Protected: Bool(true),
   320  			},
   321  		},
   322  		Rules: []*RepositoryRule{
   323  			NewCreationRule(),
   324  			NewUpdateRule(&UpdateAllowsFetchAndMergeRuleParameters{
   325  				UpdateAllowsFetchAndMerge: true,
   326  			}),
   327  			NewDeletionRule(),
   328  			NewRequiredLinearHistoryRule(),
   329  			NewRequiredDeploymentsRule(&RequiredDeploymentEnvironmentsRuleParameters{
   330  				RequiredDeploymentEnvironments: []string{"test"},
   331  			}),
   332  			NewRequiredSignaturesRule(),
   333  			NewPullRequestRule(&PullRequestRuleParameters{
   334  				RequireCodeOwnerReview:         true,
   335  				RequireLastPushApproval:        true,
   336  				RequiredApprovingReviewCount:   1,
   337  				RequiredReviewThreadResolution: true,
   338  				DismissStaleReviewsOnPush:      true,
   339  			}),
   340  			NewRequiredStatusChecksRule(&RequiredStatusChecksRuleParameters{
   341  				RequiredStatusChecks: []RuleRequiredStatusChecks{
   342  					{
   343  						Context:       "test",
   344  						IntegrationID: Int64(1),
   345  					},
   346  				},
   347  				StrictRequiredStatusChecksPolicy: true,
   348  			}),
   349  			NewNonFastForwardRule(),
   350  			NewCommitMessagePatternRule(&RulePatternParameters{
   351  				Name:     String("avoid test commits"),
   352  				Negate:   Bool(true),
   353  				Operator: "starts_with",
   354  				Pattern:  "[test]",
   355  			}),
   356  			NewCommitAuthorEmailPatternRule(&RulePatternParameters{
   357  				Operator: "contains",
   358  				Pattern:  "github",
   359  			}),
   360  			NewCommitterEmailPatternRule(&RulePatternParameters{
   361  				Name:     String("avoid commit emails"),
   362  				Negate:   Bool(true),
   363  				Operator: "ends_with",
   364  				Pattern:  "abc",
   365  			}),
   366  			NewBranchNamePatternRule(&RulePatternParameters{
   367  				Name:     String("avoid branch names"),
   368  				Negate:   Bool(true),
   369  				Operator: "regex",
   370  				Pattern:  "github$",
   371  			}),
   372  			NewTagNamePatternRule(&RulePatternParameters{
   373  				Name:     String("avoid tag names"),
   374  				Negate:   Bool(true),
   375  				Operator: "contains",
   376  				Pattern:  "github",
   377  			}),
   378  		},
   379  	}
   380  	if !cmp.Equal(ruleset, want) {
   381  		t.Errorf("Organizations.CreateOrganizationRuleset returned %+v, want %+v", ruleset, want)
   382  	}
   383  
   384  	const methodName = "CreateOrganizationRuleset"
   385  
   386  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   387  		got, resp, err := client.Organizations.CreateOrganizationRuleset(ctx, "o", nil)
   388  		if got != nil {
   389  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   390  		}
   391  		return resp, err
   392  	})
   393  }
   394  
   395  func TestOrganizationsService_GetOrganizationRuleset(t *testing.T) {
   396  	client, mux, _, teardown := setup()
   397  	defer teardown()
   398  
   399  	mux.HandleFunc("/orgs/o/rulesets/26110", func(w http.ResponseWriter, r *http.Request) {
   400  		testMethod(t, r, "GET")
   401  		fmt.Fprint(w, `{
   402  			"id": 26110,
   403  			"name": "test ruleset",
   404  			"target": "branch",
   405  			"source_type": "Organization",
   406  			"source": "o",
   407  			"enforcement": "active",
   408  			"bypass_mode": "none",
   409  			"node_id": "nid",
   410  			"_links": {
   411  			  "self": {
   412  				"href": "https://api.github.com/orgs/o/rulesets/26110"
   413  			  }
   414  			},
   415  			"conditions": {
   416  				"ref_name": {
   417  				  "include": [
   418  					"refs/heads/main",
   419  					"refs/heads/master"
   420  				  ],
   421  				  "exclude": [
   422  					"refs/heads/dev*"
   423  				  ]
   424  				},
   425  				"repository_name": {
   426  				  "include": [
   427  					"important_repository",
   428  					"another_important_repository"
   429  				  ],
   430  				  "exclude": [
   431  					"unimportant_repository"
   432  				  ],
   433  				  "protected": true
   434  				}
   435  			  },
   436  			  "rules": [
   437  				{
   438  				  "type": "creation"
   439  				}
   440  			  ]
   441  		}`)
   442  	})
   443  
   444  	ctx := context.Background()
   445  	rulesets, _, err := client.Organizations.GetOrganizationRuleset(ctx, "o", 26110)
   446  	if err != nil {
   447  		t.Errorf("Organizations.GetOrganizationRepositoryRuleset returned error: %v", err)
   448  	}
   449  
   450  	want := &Ruleset{
   451  		ID:          26110,
   452  		Name:        "test ruleset",
   453  		Target:      String("branch"),
   454  		SourceType:  String("Organization"),
   455  		Source:      "o",
   456  		Enforcement: "active",
   457  		BypassMode:  String("none"),
   458  		NodeID:      String("nid"),
   459  		Links: &RulesetLinks{
   460  			Self: &RulesetLink{HRef: String("https://api.github.com/orgs/o/rulesets/26110")},
   461  		},
   462  		Conditions: &RulesetConditions{
   463  			RefName: &RulesetRefConditionParameters{
   464  				Include: []string{"refs/heads/main", "refs/heads/master"},
   465  				Exclude: []string{"refs/heads/dev*"},
   466  			},
   467  			RepositoryName: &RulesetRepositoryConditionParameters{
   468  				Include:   []string{"important_repository", "another_important_repository"},
   469  				Exclude:   []string{"unimportant_repository"},
   470  				Protected: Bool(true),
   471  			},
   472  		},
   473  		Rules: []*RepositoryRule{
   474  			NewCreationRule(),
   475  		},
   476  	}
   477  	if !cmp.Equal(rulesets, want) {
   478  		t.Errorf("Organizations.GetOrganizationRuleset returned %+v, want %+v", rulesets, want)
   479  	}
   480  
   481  	const methodName = "GetOrganizationRuleset"
   482  
   483  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   484  		got, resp, err := client.Organizations.GetOrganizationRuleset(ctx, "o", 26110)
   485  		if got != nil {
   486  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   487  		}
   488  		return resp, err
   489  	})
   490  }
   491  
   492  func TestOrganizationsService_UpdateOrganizationRuleset(t *testing.T) {
   493  	client, mux, _, teardown := setup()
   494  	defer teardown()
   495  
   496  	mux.HandleFunc("/orgs/o/rulesets/26110", func(w http.ResponseWriter, r *http.Request) {
   497  		testMethod(t, r, "PUT")
   498  		fmt.Fprint(w, `{
   499  			"id": 26110,
   500  			"name": "test ruleset",
   501  			"target": "branch",
   502  			"source_type": "Organization",
   503  			"source": "o",
   504  			"enforcement": "active",
   505  			"bypass_mode": "none",
   506  			"node_id": "nid",
   507  			"_links": {
   508  			  "self": {
   509  				"href": "https://api.github.com/orgs/o/rulesets/26110"
   510  			  }
   511  			},
   512  			"conditions": {
   513  				"ref_name": {
   514  				  "include": [
   515  					"refs/heads/main",
   516  					"refs/heads/master"
   517  				  ],
   518  				  "exclude": [
   519  					"refs/heads/dev*"
   520  				  ]
   521  				},
   522  				"repository_name": {
   523  				  "include": [
   524  					"important_repository",
   525  					"another_important_repository"
   526  				  ],
   527  				  "exclude": [
   528  					"unimportant_repository"
   529  				  ],
   530  				  "protected": true
   531  				}
   532  			  },
   533  			  "rules": [
   534  				{
   535  				  "type": "creation"
   536  				}
   537  			  ]
   538  		}`)
   539  	})
   540  
   541  	ctx := context.Background()
   542  	rulesets, _, err := client.Organizations.UpdateOrganizationRuleset(ctx, "o", 26110, &Ruleset{
   543  		Name:        "test ruleset",
   544  		Target:      String("branch"),
   545  		Enforcement: "active",
   546  		BypassMode:  String("none"),
   547  		Conditions: &RulesetConditions{
   548  			RefName: &RulesetRefConditionParameters{
   549  				Include: []string{"refs/heads/main", "refs/heads/master"},
   550  				Exclude: []string{"refs/heads/dev*"},
   551  			},
   552  			RepositoryName: &RulesetRepositoryConditionParameters{
   553  				Include:   []string{"important_repository", "another_important_repository"},
   554  				Exclude:   []string{"unimportant_repository"},
   555  				Protected: Bool(true),
   556  			},
   557  		},
   558  		Rules: []*RepositoryRule{
   559  			NewCreationRule(),
   560  		},
   561  	})
   562  
   563  	if err != nil {
   564  		t.Errorf("Organizations.UpdateOrganizationRuleset returned error: %v", err)
   565  	}
   566  
   567  	want := &Ruleset{
   568  		ID:          26110,
   569  		Name:        "test ruleset",
   570  		Target:      String("branch"),
   571  		SourceType:  String("Organization"),
   572  		Source:      "o",
   573  		Enforcement: "active",
   574  		BypassMode:  String("none"),
   575  		NodeID:      String("nid"),
   576  		Links: &RulesetLinks{
   577  			Self: &RulesetLink{HRef: String("https://api.github.com/orgs/o/rulesets/26110")},
   578  		},
   579  		Conditions: &RulesetConditions{
   580  			RefName: &RulesetRefConditionParameters{
   581  				Include: []string{"refs/heads/main", "refs/heads/master"},
   582  				Exclude: []string{"refs/heads/dev*"},
   583  			},
   584  			RepositoryName: &RulesetRepositoryConditionParameters{
   585  				Include:   []string{"important_repository", "another_important_repository"},
   586  				Exclude:   []string{"unimportant_repository"},
   587  				Protected: Bool(true),
   588  			},
   589  		},
   590  		Rules: []*RepositoryRule{
   591  			NewCreationRule(),
   592  		},
   593  	}
   594  	if !cmp.Equal(rulesets, want) {
   595  		t.Errorf("Organizations.UpdateOrganizationRuleset returned %+v, want %+v", rulesets, want)
   596  	}
   597  
   598  	const methodName = "UpdateOrganizationRuleset"
   599  
   600  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   601  		got, resp, err := client.Organizations.UpdateOrganizationRuleset(ctx, "o", 26110, nil)
   602  		if got != nil {
   603  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   604  		}
   605  		return resp, err
   606  	})
   607  }
   608  
   609  func TestOrganizationsService_DeleteOrganizationRuleset(t *testing.T) {
   610  	client, mux, _, teardown := setup()
   611  	defer teardown()
   612  
   613  	mux.HandleFunc("/orgs/o/rulesets/26110", func(w http.ResponseWriter, r *http.Request) {
   614  		testMethod(t, r, "DELETE")
   615  	})
   616  
   617  	ctx := context.Background()
   618  	_, err := client.Organizations.DeleteOrganizationRuleset(ctx, "o", 26110)
   619  	if err != nil {
   620  		t.Errorf("Organizations.DeleteOrganizationRuleset returned error: %v", err)
   621  	}
   622  
   623  	const methodName = "DeleteOrganizationRuleset"
   624  
   625  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   626  		return client.Organizations.DeleteOrganizationRuleset(ctx, "0", 26110)
   627  	})
   628  }