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