// Copyright 2023 The go-github AUTHORS. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package github import ( "fmt" "net/http" "testing" "github.com/google/go-cmp/cmp" ) func TestOrganizationsService_ListAllRepositoryRulesets(t *testing.T) { t.Parallel() client, mux, _ := setup(t) mux.HandleFunc("/orgs/o/rulesets", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `[{ "id": 21, "name": "test ruleset", "target": "branch", "source_type": "Organization", "source": "o", "enforcement": "active", "bypass_mode": "none", "node_id": "nid", "_links": { "self": { "href": "https://api.github.com/orgs/o/rulesets/21" } } }]`) }) ctx := t.Context() rulesets, _, err := client.Organizations.ListAllRepositoryRulesets(ctx, "o", nil) if err != nil { t.Errorf("Organizations.ListAllRepositoryRulesets returned error: %v", err) } want := []*RepositoryRuleset{{ ID: new(int64(21)), Name: "test ruleset", Target: new(RulesetTargetBranch), SourceType: new(RulesetSourceTypeOrganization), Source: "o", Enforcement: "active", NodeID: new("nid"), Links: &RepositoryRulesetLinks{ Self: &RepositoryRulesetLink{HRef: new("https://api.github.com/orgs/o/rulesets/21")}, }, }} if !cmp.Equal(rulesets, want) { t.Errorf("Organizations.ListAllRepositoryRulesets returned %+v, want %+v", rulesets, want) } const methodName = "ListAllRepositoryRulesets" testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { got, resp, err := client.Organizations.ListAllRepositoryRulesets(ctx, "o", nil) if got != nil { t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) } return resp, err }) } func TestOrganizationsService_ListAllRepositoryRulesets_ListOptions(t *testing.T) { t.Parallel() client, mux, _ := setup(t) mux.HandleFunc("/orgs/o/rulesets", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") testFormValues(t, r, values{ "page": "2", "per_page": "35", }) fmt.Fprint(w, `[{ "id": 21 }]`) }) opts := &ListOptions{Page: 2, PerPage: 35} ctx := t.Context() rulesets, _, err := client.Organizations.ListAllRepositoryRulesets(ctx, "o", opts) if err != nil { t.Errorf("Organizations.ListAllRepositoryRulesets returned error: %v", err) } want := []*RepositoryRuleset{{ ID: new(int64(21)), }} if !cmp.Equal(rulesets, want) { t.Errorf("Organizations.ListAllRepositoryRulesets returned %+v, want %+v", rulesets, want) } const methodName = "ListAllRepositoryRulesets" testBadOptions(t, methodName, func() (err error) { _, _, err = client.Organizations.ListAllRepositoryRulesets(ctx, "\n", opts) return err }) testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { got, resp, err := client.Organizations.ListAllRepositoryRulesets(ctx, "o", opts) if got != nil { t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) } return resp, err }) } func TestOrganizationsService_CreateRepositoryRuleset_RepoNames(t *testing.T) { t.Parallel() client, mux, _ := setup(t) mux.HandleFunc("/orgs/o/rulesets", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "POST") fmt.Fprint(w, `{ "id": 21, "name": "ruleset", "target": "branch", "source_type": "Organization", "source": "o", "enforcement": "active", "bypass_actors": [ { "actor_id": 234, "actor_type": "Team" }, { "actor_id": 345, "actor_type": "Team", "bypass_mode": "exempt" } ], "conditions": { "ref_name": { "include": [ "refs/heads/main", "refs/heads/master" ], "exclude": [ "refs/heads/dev*" ] }, "repository_name": { "include": [ "important_repository", "another_important_repository" ], "exclude": [ "unimportant_repository" ], "protected": true } }, "rules": [ { "type": "creation" }, { "type": "update", "parameters": { "update_allows_fetch_and_merge": true } }, { "type": "deletion" }, { "type": "required_linear_history" }, { "type": "required_deployments", "parameters": { "required_deployment_environments": ["test"] } }, { "type": "required_signatures" }, { "type": "pull_request", "parameters": { "allowed_merge_methods": ["rebase","squash"], "dismiss_stale_reviews_on_push": true, "require_code_owner_review": true, "require_extra_approval_for_unattributed_changes": true, "require_last_push_approval": true, "required_approving_review_count": 1, "required_review_thread_resolution": true } }, { "type": "required_status_checks", "parameters": { "do_not_enforce_on_create": true, "required_status_checks": [ { "context": "test", "integration_id": 1 } ], "strict_required_status_checks_policy": true } }, { "type": "non_fast_forward" }, { "type": "commit_message_pattern", "parameters": { "name": "avoid test commits", "negate": true, "operator": "starts_with", "pattern": "[test]" } }, { "type": "commit_author_email_pattern", "parameters": { "operator": "contains", "pattern": "github" } }, { "type": "committer_email_pattern", "parameters": { "name": "avoid commit emails", "negate": true, "operator": "ends_with", "pattern": "abc" } }, { "type": "branch_name_pattern", "parameters": { "name": "avoid branch names", "negate": true, "operator": "regex", "pattern": "github$" } }, { "type": "tag_name_pattern", "parameters": { "name": "avoid tag names", "negate": true, "operator": "contains", "pattern": "github" } }, { "type": "code_scanning", "parameters": { "code_scanning_tools": [ { "tool": "CodeQL", "security_alerts_threshold": "high_or_higher", "alerts_threshold": "errors" } ] } } ] }`) }) ctx := t.Context() ruleset, _, err := client.Organizations.CreateRepositoryRuleset(ctx, "o", RepositoryRuleset{ Name: "ruleset", Target: new(RulesetTargetBranch), Enforcement: "active", BypassActors: []*BypassActor{ { ActorID: new(int64(234)), ActorType: new(BypassActorTypeTeam), }, { ActorID: new(int64(345)), ActorType: new(BypassActorTypeTeam), BypassMode: new(BypassModeExempt), }, }, Conditions: &RepositoryRulesetConditions{ RefName: &RepositoryRulesetRefConditionParameters{ Include: []string{"refs/heads/main", "refs/heads/master"}, Exclude: []string{"refs/heads/dev*"}, }, RepositoryName: &RepositoryRulesetRepositoryNamesConditionParameters{ Include: []string{"important_repository", "another_important_repository"}, Exclude: []string{"unimportant_repository"}, Protected: new(true), }, }, Rules: &RepositoryRulesetRules{ Creation: &EmptyRuleParameters{}, Update: &UpdateRuleParameters{ UpdateAllowsFetchAndMerge: true, }, Deletion: &EmptyRuleParameters{}, RequiredLinearHistory: &EmptyRuleParameters{}, RequiredDeployments: &RequiredDeploymentsRuleParameters{ RequiredDeploymentEnvironments: []string{"test"}, }, RequiredSignatures: &EmptyRuleParameters{}, PullRequest: &PullRequestRuleParameters{ AllowedMergeMethods: []PullRequestMergeMethod{PullRequestMergeMethodRebase, PullRequestMergeMethodSquash}, DismissStaleReviewsOnPush: true, RequireCodeOwnerReview: true, RequireExtraApprovalForUnattributedChanges: true, RequireLastPushApproval: true, RequiredApprovingReviewCount: 1, RequiredReviewThreadResolution: true, }, RequiredStatusChecks: &RequiredStatusChecksRuleParameters{ DoNotEnforceOnCreate: new(true), RequiredStatusChecks: []*RuleStatusCheck{ { Context: "test", IntegrationID: new(int64(1)), }, }, StrictRequiredStatusChecksPolicy: true, }, NonFastForward: &EmptyRuleParameters{}, CommitMessagePattern: &PatternRuleParameters{ Name: new("avoid test commits"), Negate: new(true), Operator: "starts_with", Pattern: "[test]", }, CommitAuthorEmailPattern: &PatternRuleParameters{ Operator: "contains", Pattern: "github", }, CommitterEmailPattern: &PatternRuleParameters{ Name: new("avoid commit emails"), Negate: new(true), Operator: "ends_with", Pattern: "abc", }, BranchNamePattern: &PatternRuleParameters{ Name: new("avoid branch names"), Negate: new(true), Operator: "regex", Pattern: "github$", }, TagNamePattern: &PatternRuleParameters{ Name: new("avoid tag names"), Negate: new(true), Operator: "contains", Pattern: "github", }, CodeScanning: &CodeScanningRuleParameters{ CodeScanningTools: []*RuleCodeScanningTool{ { AlertsThreshold: CodeScanningAlertsThresholdErrors, SecurityAlertsThreshold: CodeScanningSecurityAlertsThresholdHighOrHigher, Tool: "CodeQL", }, }, }, }, }) if err != nil { t.Errorf("Organizations.CreateRepositoryRuleset returned error: %v", err) } want := &RepositoryRuleset{ ID: new(int64(21)), Name: "ruleset", Target: new(RulesetTargetBranch), SourceType: new(RulesetSourceTypeOrganization), Source: "o", Enforcement: "active", BypassActors: []*BypassActor{ { ActorID: new(int64(234)), ActorType: new(BypassActorTypeTeam), }, { ActorID: new(int64(345)), ActorType: new(BypassActorTypeTeam), BypassMode: new(BypassModeExempt), }, }, Conditions: &RepositoryRulesetConditions{ RefName: &RepositoryRulesetRefConditionParameters{ Include: []string{"refs/heads/main", "refs/heads/master"}, Exclude: []string{"refs/heads/dev*"}, }, RepositoryName: &RepositoryRulesetRepositoryNamesConditionParameters{ Include: []string{"important_repository", "another_important_repository"}, Exclude: []string{"unimportant_repository"}, Protected: new(true), }, }, Rules: &RepositoryRulesetRules{ Creation: &EmptyRuleParameters{}, Update: &UpdateRuleParameters{ UpdateAllowsFetchAndMerge: true, }, Deletion: &EmptyRuleParameters{}, RequiredLinearHistory: &EmptyRuleParameters{}, RequiredDeployments: &RequiredDeploymentsRuleParameters{ RequiredDeploymentEnvironments: []string{"test"}, }, RequiredSignatures: &EmptyRuleParameters{}, PullRequest: &PullRequestRuleParameters{ AllowedMergeMethods: []PullRequestMergeMethod{PullRequestMergeMethodRebase, PullRequestMergeMethodSquash}, DismissStaleReviewsOnPush: true, RequireCodeOwnerReview: true, RequireExtraApprovalForUnattributedChanges: true, RequireLastPushApproval: true, RequiredApprovingReviewCount: 1, RequiredReviewThreadResolution: true, }, RequiredStatusChecks: &RequiredStatusChecksRuleParameters{ DoNotEnforceOnCreate: new(true), RequiredStatusChecks: []*RuleStatusCheck{ { Context: "test", IntegrationID: new(int64(1)), }, }, StrictRequiredStatusChecksPolicy: true, }, NonFastForward: &EmptyRuleParameters{}, CommitMessagePattern: &PatternRuleParameters{ Name: new("avoid test commits"), Negate: new(true), Operator: "starts_with", Pattern: "[test]", }, CommitAuthorEmailPattern: &PatternRuleParameters{ Operator: "contains", Pattern: "github", }, CommitterEmailPattern: &PatternRuleParameters{ Name: new("avoid commit emails"), Negate: new(true), Operator: "ends_with", Pattern: "abc", }, BranchNamePattern: &PatternRuleParameters{ Name: new("avoid branch names"), Negate: new(true), Operator: "regex", Pattern: "github$", }, TagNamePattern: &PatternRuleParameters{ Name: new("avoid tag names"), Negate: new(true), Operator: "contains", Pattern: "github", }, CodeScanning: &CodeScanningRuleParameters{ CodeScanningTools: []*RuleCodeScanningTool{ { AlertsThreshold: CodeScanningAlertsThresholdErrors, SecurityAlertsThreshold: CodeScanningSecurityAlertsThresholdHighOrHigher, Tool: "CodeQL", }, }, }, }, } if !cmp.Equal(ruleset, want) { t.Errorf("Organizations.CreateRepositoryRuleset returned %+v, want %+v", ruleset, want) } const methodName = "CreateRepositoryRuleset" testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { got, resp, err := client.Organizations.CreateRepositoryRuleset(ctx, "o", RepositoryRuleset{}) if got != nil { t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) } return resp, err }) } func TestOrganizationsService_CreateRepositoryRuleset_RepoProperty(t *testing.T) { t.Parallel() client, mux, _ := setup(t) mux.HandleFunc("/orgs/o/rulesets", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "POST") fmt.Fprint(w, `{ "id": 21, "name": "ruleset", "target": "branch", "source_type": "Organization", "source": "o", "enforcement": "active", "bypass_actors": [ { "actor_id": 234, "actor_type": "Team" } ], "conditions": { "repository_property": { "include": [ { "name": "testIncludeProp", "source": "custom", "property_values": [ "true" ] } ], "exclude": [ { "name": "testExcludeProp", "property_values": [ "false" ] } ] } }, "rules": [ { "type": "creation" }, { "type": "update", "parameters": { "update_allows_fetch_and_merge": true } }, { "type": "deletion" }, { "type": "required_linear_history" }, { "type": "required_deployments", "parameters": { "required_deployment_environments": ["test"] } }, { "type": "required_signatures" }, { "type": "pull_request", "parameters": { "allowed_merge_methods": ["rebase","squash"], "dismiss_stale_reviews_on_push": true, "require_code_owner_review": true, "require_extra_approval_for_unattributed_changes": true, "require_last_push_approval": true, "required_approving_review_count": 1, "required_review_thread_resolution": true } }, { "type": "required_status_checks", "parameters": { "do_not_enforce_on_create": true, "required_status_checks": [ { "context": "test", "integration_id": 1 } ], "strict_required_status_checks_policy": true } }, { "type": "non_fast_forward" }, { "type": "commit_message_pattern", "parameters": { "name": "avoid test commits", "negate": true, "operator": "starts_with", "pattern": "[test]" } }, { "type": "commit_author_email_pattern", "parameters": { "operator": "contains", "pattern": "github" } }, { "type": "committer_email_pattern", "parameters": { "name": "avoid commit emails", "negate": true, "operator": "ends_with", "pattern": "abc" } }, { "type": "branch_name_pattern", "parameters": { "name": "avoid branch names", "negate": true, "operator": "regex", "pattern": "github$" } }, { "type": "tag_name_pattern", "parameters": { "name": "avoid tag names", "negate": true, "operator": "contains", "pattern": "github" } }, { "type": "code_scanning", "parameters": { "code_scanning_tools": [ { "tool": "CodeQL", "security_alerts_threshold": "high_or_higher", "alerts_threshold": "errors" } ] } } ] }`) }) ctx := t.Context() ruleset, _, err := client.Organizations.CreateRepositoryRuleset(ctx, "o", RepositoryRuleset{ Name: "ruleset", Target: new(RulesetTargetBranch), Enforcement: "active", BypassActors: []*BypassActor{ { ActorID: new(int64(234)), ActorType: new(BypassActorTypeTeam), }, }, Conditions: &RepositoryRulesetConditions{ RepositoryProperty: &RepositoryRulesetRepositoryPropertyConditionParameters{ Include: []*RepositoryRulesetRepositoryPropertyTargetParameters{ { Name: "testIncludeProp", Source: new("custom"), PropertyValues: []string{"true"}, }, }, Exclude: []*RepositoryRulesetRepositoryPropertyTargetParameters{ { Name: "testExcludeProp", PropertyValues: []string{"false"}, }, }, }, }, Rules: &RepositoryRulesetRules{ Creation: &EmptyRuleParameters{}, Update: &UpdateRuleParameters{ UpdateAllowsFetchAndMerge: true, }, Deletion: &EmptyRuleParameters{}, RequiredLinearHistory: &EmptyRuleParameters{}, RequiredDeployments: &RequiredDeploymentsRuleParameters{ RequiredDeploymentEnvironments: []string{"test"}, }, RequiredSignatures: &EmptyRuleParameters{}, PullRequest: &PullRequestRuleParameters{ AllowedMergeMethods: []PullRequestMergeMethod{PullRequestMergeMethodRebase, PullRequestMergeMethodSquash}, DismissStaleReviewsOnPush: true, RequireCodeOwnerReview: true, RequireExtraApprovalForUnattributedChanges: true, RequireLastPushApproval: true, RequiredApprovingReviewCount: 1, RequiredReviewThreadResolution: true, }, RequiredStatusChecks: &RequiredStatusChecksRuleParameters{ DoNotEnforceOnCreate: new(true), RequiredStatusChecks: []*RuleStatusCheck{ { Context: "test", IntegrationID: new(int64(1)), }, }, StrictRequiredStatusChecksPolicy: true, }, NonFastForward: &EmptyRuleParameters{}, CommitMessagePattern: &PatternRuleParameters{ Name: new("avoid test commits"), Negate: new(true), Operator: "starts_with", Pattern: "[test]", }, CommitAuthorEmailPattern: &PatternRuleParameters{ Operator: "contains", Pattern: "github", }, CommitterEmailPattern: &PatternRuleParameters{ Name: new("avoid commit emails"), Negate: new(true), Operator: "ends_with", Pattern: "abc", }, BranchNamePattern: &PatternRuleParameters{ Name: new("avoid branch names"), Negate: new(true), Operator: "regex", Pattern: "github$", }, TagNamePattern: &PatternRuleParameters{ Name: new("avoid tag names"), Negate: new(true), Operator: "contains", Pattern: "github", }, CodeScanning: &CodeScanningRuleParameters{ CodeScanningTools: []*RuleCodeScanningTool{ { AlertsThreshold: CodeScanningAlertsThresholdErrors, SecurityAlertsThreshold: CodeScanningSecurityAlertsThresholdHighOrHigher, Tool: "CodeQL", }, }, }, }, }) if err != nil { t.Errorf("Organizations.CreateRepositoryRuleset returned error: %v", err) } want := &RepositoryRuleset{ ID: new(int64(21)), Name: "ruleset", Target: new(RulesetTargetBranch), SourceType: new(RulesetSourceTypeOrganization), Source: "o", Enforcement: "active", BypassActors: []*BypassActor{ { ActorID: new(int64(234)), ActorType: new(BypassActorTypeTeam), }, }, Conditions: &RepositoryRulesetConditions{ RepositoryProperty: &RepositoryRulesetRepositoryPropertyConditionParameters{ Include: []*RepositoryRulesetRepositoryPropertyTargetParameters{ { Name: "testIncludeProp", Source: new("custom"), PropertyValues: []string{"true"}, }, }, Exclude: []*RepositoryRulesetRepositoryPropertyTargetParameters{ { Name: "testExcludeProp", PropertyValues: []string{"false"}, }, }, }, }, Rules: &RepositoryRulesetRules{ Creation: &EmptyRuleParameters{}, Update: &UpdateRuleParameters{ UpdateAllowsFetchAndMerge: true, }, Deletion: &EmptyRuleParameters{}, RequiredLinearHistory: &EmptyRuleParameters{}, RequiredDeployments: &RequiredDeploymentsRuleParameters{ RequiredDeploymentEnvironments: []string{"test"}, }, RequiredSignatures: &EmptyRuleParameters{}, PullRequest: &PullRequestRuleParameters{ AllowedMergeMethods: []PullRequestMergeMethod{PullRequestMergeMethodRebase, PullRequestMergeMethodSquash}, DismissStaleReviewsOnPush: true, RequireCodeOwnerReview: true, RequireExtraApprovalForUnattributedChanges: true, RequireLastPushApproval: true, RequiredApprovingReviewCount: 1, RequiredReviewThreadResolution: true, }, RequiredStatusChecks: &RequiredStatusChecksRuleParameters{ DoNotEnforceOnCreate: new(true), RequiredStatusChecks: []*RuleStatusCheck{ { Context: "test", IntegrationID: new(int64(1)), }, }, StrictRequiredStatusChecksPolicy: true, }, NonFastForward: &EmptyRuleParameters{}, CommitMessagePattern: &PatternRuleParameters{ Name: new("avoid test commits"), Negate: new(true), Operator: "starts_with", Pattern: "[test]", }, CommitAuthorEmailPattern: &PatternRuleParameters{ Operator: "contains", Pattern: "github", }, CommitterEmailPattern: &PatternRuleParameters{ Name: new("avoid commit emails"), Negate: new(true), Operator: "ends_with", Pattern: "abc", }, BranchNamePattern: &PatternRuleParameters{ Name: new("avoid branch names"), Negate: new(true), Operator: "regex", Pattern: "github$", }, TagNamePattern: &PatternRuleParameters{ Name: new("avoid tag names"), Negate: new(true), Operator: "contains", Pattern: "github", }, CodeScanning: &CodeScanningRuleParameters{ CodeScanningTools: []*RuleCodeScanningTool{ { AlertsThreshold: CodeScanningAlertsThresholdErrors, SecurityAlertsThreshold: CodeScanningSecurityAlertsThresholdHighOrHigher, Tool: "CodeQL", }, }, }, }, } if !cmp.Equal(ruleset, want) { t.Errorf("Organizations.CreateRepositoryRuleset returned %+v, want %+v", ruleset, want) } const methodName = "CreateRepositoryRuleset" testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { got, resp, err := client.Organizations.CreateRepositoryRuleset(ctx, "o", RepositoryRuleset{}) if got != nil { t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) } return resp, err }) } func TestOrganizationsService_CreateRepositoryRuleset_RepoIDs(t *testing.T) { t.Parallel() client, mux, _ := setup(t) mux.HandleFunc("/orgs/o/rulesets", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "POST") fmt.Fprint(w, `{ "id": 21, "name": "ruleset", "target": "branch", "source_type": "Organization", "source": "o", "enforcement": "active", "bypass_actors": [ { "actor_id": 234, "actor_type": "Team" } ], "conditions": { "ref_name": { "include": [ "refs/heads/main", "refs/heads/master" ], "exclude": [ "refs/heads/dev*" ] }, "repository_id": { "repository_ids": [ 123, 456 ] } }, "rules": [ { "type": "creation" }, { "type": "update", "parameters": { "update_allows_fetch_and_merge": true } }, { "type": "deletion" }, { "type": "required_linear_history" }, { "type": "required_deployments", "parameters": { "required_deployment_environments": ["test"] } }, { "type": "required_signatures" }, { "type": "pull_request", "parameters": { "allowed_merge_methods": ["rebase","squash"], "dismiss_stale_reviews_on_push": true, "require_code_owner_review": true, "require_extra_approval_for_unattributed_changes": true, "require_last_push_approval": true, "required_approving_review_count": 1, "required_review_thread_resolution": true } }, { "type": "required_status_checks", "parameters": { "do_not_enforce_on_create": true, "required_status_checks": [ { "context": "test", "integration_id": 1 } ], "strict_required_status_checks_policy": true } }, { "type": "non_fast_forward" }, { "type": "commit_message_pattern", "parameters": { "name": "avoid test commits", "negate": true, "operator": "starts_with", "pattern": "[test]" } }, { "type": "commit_author_email_pattern", "parameters": { "operator": "contains", "pattern": "github" } }, { "type": "committer_email_pattern", "parameters": { "name": "avoid commit emails", "negate": true, "operator": "ends_with", "pattern": "abc" } }, { "type": "branch_name_pattern", "parameters": { "name": "avoid branch names", "negate": true, "operator": "regex", "pattern": "github$" } }, { "type": "tag_name_pattern", "parameters": { "name": "avoid tag names", "negate": true, "operator": "contains", "pattern": "github" } }, { "type": "code_scanning", "parameters": { "code_scanning_tools": [ { "tool": "CodeQL", "security_alerts_threshold": "high_or_higher", "alerts_threshold": "errors" } ] } } ] }`) }) ctx := t.Context() ruleset, _, err := client.Organizations.CreateRepositoryRuleset(ctx, "o", RepositoryRuleset{ Name: "ruleset", Target: new(RulesetTargetBranch), Enforcement: "active", BypassActors: []*BypassActor{ { ActorID: new(int64(234)), ActorType: new(BypassActorTypeTeam), }, }, Conditions: &RepositoryRulesetConditions{ RefName: &RepositoryRulesetRefConditionParameters{ Include: []string{"refs/heads/main", "refs/heads/master"}, Exclude: []string{"refs/heads/dev*"}, }, RepositoryID: &RepositoryRulesetRepositoryIDsConditionParameters{ RepositoryIDs: []int64{123, 456}, }, }, Rules: &RepositoryRulesetRules{ Creation: &EmptyRuleParameters{}, Update: &UpdateRuleParameters{ UpdateAllowsFetchAndMerge: true, }, Deletion: &EmptyRuleParameters{}, RequiredLinearHistory: &EmptyRuleParameters{}, RequiredDeployments: &RequiredDeploymentsRuleParameters{ RequiredDeploymentEnvironments: []string{"test"}, }, RequiredSignatures: &EmptyRuleParameters{}, PullRequest: &PullRequestRuleParameters{ AllowedMergeMethods: []PullRequestMergeMethod{PullRequestMergeMethodRebase, PullRequestMergeMethodSquash}, DismissStaleReviewsOnPush: true, RequireCodeOwnerReview: true, RequireExtraApprovalForUnattributedChanges: true, RequireLastPushApproval: true, RequiredApprovingReviewCount: 1, RequiredReviewThreadResolution: true, }, RequiredStatusChecks: &RequiredStatusChecksRuleParameters{ DoNotEnforceOnCreate: new(true), RequiredStatusChecks: []*RuleStatusCheck{ { Context: "test", IntegrationID: new(int64(1)), }, }, StrictRequiredStatusChecksPolicy: true, }, NonFastForward: &EmptyRuleParameters{}, CommitMessagePattern: &PatternRuleParameters{ Name: new("avoid test commits"), Negate: new(true), Operator: "starts_with", Pattern: "[test]", }, CommitAuthorEmailPattern: &PatternRuleParameters{ Operator: "contains", Pattern: "github", }, CommitterEmailPattern: &PatternRuleParameters{ Name: new("avoid commit emails"), Negate: new(true), Operator: "ends_with", Pattern: "abc", }, BranchNamePattern: &PatternRuleParameters{ Name: new("avoid branch names"), Negate: new(true), Operator: "regex", Pattern: "github$", }, TagNamePattern: &PatternRuleParameters{ Name: new("avoid tag names"), Negate: new(true), Operator: "contains", Pattern: "github", }, CodeScanning: &CodeScanningRuleParameters{ CodeScanningTools: []*RuleCodeScanningTool{ { AlertsThreshold: CodeScanningAlertsThresholdErrors, SecurityAlertsThreshold: CodeScanningSecurityAlertsThresholdHighOrHigher, Tool: "CodeQL", }, }, }, }, }) if err != nil { t.Errorf("Organizations.CreateRepositoryRuleset returned error: %v", err) } want := &RepositoryRuleset{ ID: new(int64(21)), Name: "ruleset", Target: new(RulesetTargetBranch), SourceType: new(RulesetSourceTypeOrganization), Source: "o", Enforcement: "active", BypassActors: []*BypassActor{ { ActorID: new(int64(234)), ActorType: new(BypassActorTypeTeam), }, }, Conditions: &RepositoryRulesetConditions{ RefName: &RepositoryRulesetRefConditionParameters{ Include: []string{"refs/heads/main", "refs/heads/master"}, Exclude: []string{"refs/heads/dev*"}, }, RepositoryID: &RepositoryRulesetRepositoryIDsConditionParameters{ RepositoryIDs: []int64{123, 456}, }, }, Rules: &RepositoryRulesetRules{ Creation: &EmptyRuleParameters{}, Update: &UpdateRuleParameters{ UpdateAllowsFetchAndMerge: true, }, Deletion: &EmptyRuleParameters{}, RequiredLinearHistory: &EmptyRuleParameters{}, RequiredDeployments: &RequiredDeploymentsRuleParameters{ RequiredDeploymentEnvironments: []string{"test"}, }, RequiredSignatures: &EmptyRuleParameters{}, PullRequest: &PullRequestRuleParameters{ AllowedMergeMethods: []PullRequestMergeMethod{PullRequestMergeMethodRebase, PullRequestMergeMethodSquash}, DismissStaleReviewsOnPush: true, RequireCodeOwnerReview: true, RequireExtraApprovalForUnattributedChanges: true, RequireLastPushApproval: true, RequiredApprovingReviewCount: 1, RequiredReviewThreadResolution: true, }, RequiredStatusChecks: &RequiredStatusChecksRuleParameters{ DoNotEnforceOnCreate: new(true), RequiredStatusChecks: []*RuleStatusCheck{ { Context: "test", IntegrationID: new(int64(1)), }, }, StrictRequiredStatusChecksPolicy: true, }, NonFastForward: &EmptyRuleParameters{}, CommitMessagePattern: &PatternRuleParameters{ Name: new("avoid test commits"), Negate: new(true), Operator: "starts_with", Pattern: "[test]", }, CommitAuthorEmailPattern: &PatternRuleParameters{ Operator: "contains", Pattern: "github", }, CommitterEmailPattern: &PatternRuleParameters{ Name: new("avoid commit emails"), Negate: new(true), Operator: "ends_with", Pattern: "abc", }, BranchNamePattern: &PatternRuleParameters{ Name: new("avoid branch names"), Negate: new(true), Operator: "regex", Pattern: "github$", }, TagNamePattern: &PatternRuleParameters{ Name: new("avoid tag names"), Negate: new(true), Operator: "contains", Pattern: "github", }, CodeScanning: &CodeScanningRuleParameters{ CodeScanningTools: []*RuleCodeScanningTool{ { AlertsThreshold: CodeScanningAlertsThresholdErrors, SecurityAlertsThreshold: CodeScanningSecurityAlertsThresholdHighOrHigher, Tool: "CodeQL", }, }, }, }, } if !cmp.Equal(ruleset, want) { t.Errorf("Organizations.CreateRepositoryRuleset returned %+v, want %+v", ruleset, want) } const methodName = "CreateRepositoryRuleset" testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { got, resp, err := client.Organizations.CreateRepositoryRuleset(ctx, "o", RepositoryRuleset{}) if got != nil { t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) } return resp, err }) } func TestOrganizationsService_GetRepositoryRuleset(t *testing.T) { t.Parallel() client, mux, _ := setup(t) mux.HandleFunc("/orgs/o/rulesets/21", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{ "id": 21, "name": "test ruleset", "target": "branch", "source_type": "Organization", "source": "o", "enforcement": "active", "bypass_mode": "none", "node_id": "nid", "_links": { "self": { "href": "https://api.github.com/orgs/o/rulesets/21" } }, "conditions": { "ref_name": { "include": [ "refs/heads/main", "refs/heads/master" ], "exclude": [ "refs/heads/dev*" ] }, "repository_name": { "include": [ "important_repository", "another_important_repository" ], "exclude": [ "unimportant_repository" ], "protected": true } }, "rules": [ { "type": "creation" } ] }`) }) ctx := t.Context() rulesets, _, err := client.Organizations.GetRepositoryRuleset(ctx, "o", 21) if err != nil { t.Errorf("Organizations.GetRepositoryRuleset returned error: %v", err) } want := &RepositoryRuleset{ ID: new(int64(21)), Name: "test ruleset", Target: new(RulesetTargetBranch), SourceType: new(RulesetSourceTypeOrganization), Source: "o", Enforcement: "active", NodeID: new("nid"), Links: &RepositoryRulesetLinks{ Self: &RepositoryRulesetLink{HRef: new("https://api.github.com/orgs/o/rulesets/21")}, }, Conditions: &RepositoryRulesetConditions{ RefName: &RepositoryRulesetRefConditionParameters{ Include: []string{"refs/heads/main", "refs/heads/master"}, Exclude: []string{"refs/heads/dev*"}, }, RepositoryName: &RepositoryRulesetRepositoryNamesConditionParameters{ Include: []string{"important_repository", "another_important_repository"}, Exclude: []string{"unimportant_repository"}, Protected: new(true), }, }, Rules: &RepositoryRulesetRules{Creation: &EmptyRuleParameters{}}, } if !cmp.Equal(rulesets, want) { t.Errorf("Organizations.GetRepositoryRuleset returned %+v, want %+v", rulesets, want) } const methodName = "GetRepositoryRuleset" testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { got, resp, err := client.Organizations.GetRepositoryRuleset(ctx, "o", 21) if got != nil { t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) } return resp, err }) } func TestOrganizationsService_GetRepositoryRulesetWithRepoPropCondition(t *testing.T) { t.Parallel() client, mux, _ := setup(t) mux.HandleFunc("/orgs/o/rulesets/21", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") fmt.Fprint(w, `{ "id": 21, "name": "test ruleset", "target": "branch", "source_type": "Organization", "source": "o", "enforcement": "active", "bypass_mode": "none", "node_id": "nid", "_links": { "self": { "href": "https://api.github.com/orgs/o/rulesets/21" } }, "conditions": { "repository_property": { "exclude": [], "include": [ { "name": "testIncludeProp", "source": "custom", "property_values": [ "true" ] } ] } }, "rules": [ { "type": "creation" } ] }`) }) ctx := t.Context() rulesets, _, err := client.Organizations.GetRepositoryRuleset(ctx, "o", 21) if err != nil { t.Errorf("Organizations.GetRepositoryRuleset returned error: %v", err) } want := &RepositoryRuleset{ ID: new(int64(21)), Name: "test ruleset", Target: new(RulesetTargetBranch), SourceType: new(RulesetSourceTypeOrganization), Source: "o", Enforcement: "active", NodeID: new("nid"), Links: &RepositoryRulesetLinks{ Self: &RepositoryRulesetLink{HRef: new("https://api.github.com/orgs/o/rulesets/21")}, }, Conditions: &RepositoryRulesetConditions{ RepositoryProperty: &RepositoryRulesetRepositoryPropertyConditionParameters{ Include: []*RepositoryRulesetRepositoryPropertyTargetParameters{ { Name: "testIncludeProp", Source: new("custom"), PropertyValues: []string{"true"}, }, }, Exclude: []*RepositoryRulesetRepositoryPropertyTargetParameters{}, }, }, Rules: &RepositoryRulesetRules{Creation: &EmptyRuleParameters{}}, } if !cmp.Equal(rulesets, want) { t.Errorf("Organizations.GetRepositoryRuleset returned %+v, want %+v", rulesets, want) } const methodName = "GetRepositoryRuleset" testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { got, resp, err := client.Organizations.GetRepositoryRuleset(ctx, "o", 21) if got != nil { t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) } return resp, err }) } func TestOrganizationsService_UpdateRepositoryRuleset(t *testing.T) { t.Parallel() client, mux, _ := setup(t) mux.HandleFunc("/orgs/o/rulesets/21", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "PUT") fmt.Fprint(w, `{ "id": 21, "name": "test ruleset", "target": "branch", "source_type": "Organization", "source": "o", "enforcement": "active", "bypass_mode": "none", "node_id": "nid", "_links": { "self": { "href": "https://api.github.com/orgs/o/rulesets/21" } }, "conditions": { "ref_name": { "include": [ "refs/heads/main", "refs/heads/master" ], "exclude": [ "refs/heads/dev*" ] }, "repository_name": { "include": [ "important_repository", "another_important_repository" ], "exclude": [ "unimportant_repository" ], "protected": true } }, "rules": [ { "type": "creation" } ] }`) }) ctx := t.Context() rulesets, _, err := client.Organizations.UpdateRepositoryRuleset(ctx, "o", 21, RepositoryRuleset{ Name: "test ruleset", Target: new(RulesetTargetBranch), Enforcement: "active", Conditions: &RepositoryRulesetConditions{ RefName: &RepositoryRulesetRefConditionParameters{ Include: []string{"refs/heads/main", "refs/heads/master"}, Exclude: []string{"refs/heads/dev*"}, }, RepositoryName: &RepositoryRulesetRepositoryNamesConditionParameters{ Include: []string{"important_repository", "another_important_repository"}, Exclude: []string{"unimportant_repository"}, Protected: new(true), }, }, Rules: &RepositoryRulesetRules{Creation: &EmptyRuleParameters{}}, }) if err != nil { t.Errorf("Organizations.UpdateRepositoryRuleset returned error: %v", err) } want := &RepositoryRuleset{ ID: new(int64(21)), Name: "test ruleset", Target: new(RulesetTargetBranch), SourceType: new(RulesetSourceTypeOrganization), Source: "o", Enforcement: "active", NodeID: new("nid"), Links: &RepositoryRulesetLinks{ Self: &RepositoryRulesetLink{HRef: new("https://api.github.com/orgs/o/rulesets/21")}, }, Conditions: &RepositoryRulesetConditions{ RefName: &RepositoryRulesetRefConditionParameters{ Include: []string{"refs/heads/main", "refs/heads/master"}, Exclude: []string{"refs/heads/dev*"}, }, RepositoryName: &RepositoryRulesetRepositoryNamesConditionParameters{ Include: []string{"important_repository", "another_important_repository"}, Exclude: []string{"unimportant_repository"}, Protected: new(true), }, }, Rules: &RepositoryRulesetRules{Creation: &EmptyRuleParameters{}}, } if !cmp.Equal(rulesets, want) { t.Errorf("Organizations.UpdateRepositoryRuleset returned %+v, want %+v", rulesets, want) } const methodName = "UpdateRepositoryRuleset" testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { got, resp, err := client.Organizations.UpdateRepositoryRuleset(ctx, "o", 21, RepositoryRuleset{}) if got != nil { t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) } return resp, err }) } func TestOrganizationsService_UpdateRepositoryRulesetWithRepoProp(t *testing.T) { t.Parallel() client, mux, _ := setup(t) mux.HandleFunc("/orgs/o/rulesets/21", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "PUT") fmt.Fprint(w, `{ "id": 21, "name": "test ruleset", "target": "branch", "source_type": "Organization", "source": "o", "enforcement": "active", "bypass_mode": "none", "node_id": "nid", "_links": { "self": { "href": "https://api.github.com/orgs/o/rulesets/21" } }, "conditions": { "repository_property": { "exclude": [], "include": [ { "name": "testIncludeProp", "source": "custom", "property_values": [ "true" ] } ] } }, "rules": [ { "type": "creation" } ] }`) }) ctx := t.Context() rulesets, _, err := client.Organizations.UpdateRepositoryRuleset(ctx, "o", 21, RepositoryRuleset{ Name: "test ruleset", Target: new(RulesetTargetBranch), Enforcement: "active", Conditions: &RepositoryRulesetConditions{ RepositoryProperty: &RepositoryRulesetRepositoryPropertyConditionParameters{ Include: []*RepositoryRulesetRepositoryPropertyTargetParameters{ { Name: "testIncludeProp", Source: new("custom"), PropertyValues: []string{"true"}, }, }, Exclude: []*RepositoryRulesetRepositoryPropertyTargetParameters{}, }, }, Rules: &RepositoryRulesetRules{Creation: &EmptyRuleParameters{}}, }) if err != nil { t.Errorf("Organizations.UpdateRepositoryRuleset returned error: %v", err) } want := &RepositoryRuleset{ ID: new(int64(21)), Name: "test ruleset", Target: new(RulesetTargetBranch), SourceType: new(RulesetSourceTypeOrganization), Source: "o", Enforcement: "active", NodeID: new("nid"), Links: &RepositoryRulesetLinks{ Self: &RepositoryRulesetLink{HRef: new("https://api.github.com/orgs/o/rulesets/21")}, }, Conditions: &RepositoryRulesetConditions{ RepositoryProperty: &RepositoryRulesetRepositoryPropertyConditionParameters{ Include: []*RepositoryRulesetRepositoryPropertyTargetParameters{ { Name: "testIncludeProp", Source: new("custom"), PropertyValues: []string{"true"}, }, }, Exclude: []*RepositoryRulesetRepositoryPropertyTargetParameters{}, }, }, Rules: &RepositoryRulesetRules{Creation: &EmptyRuleParameters{}}, } if !cmp.Equal(rulesets, want) { t.Errorf("Organizations.UpdateRepositoryRuleset returned %+v, want %+v", rulesets, want) } const methodName = "UpdateRepositoryRuleset" testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { got, resp, err := client.Organizations.UpdateRepositoryRuleset(ctx, "o", 21, RepositoryRuleset{}) if got != nil { t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) } return resp, err }) } func TestOrganizationsService_UpdateRepositoryRuleset_OmitZero_Nil(t *testing.T) { t.Parallel() client, mux, _ := setup(t) input := RepositoryRuleset{ Name: "test ruleset", Enforcement: RulesetEnforcementActive, BypassActors: nil, } mux.HandleFunc("/orgs/o/rulesets/21", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "PUT") testJSONBody(t, r, input) fmt.Fprint(w, `{ "id": 21, "name": "test ruleset", "source_type": "Organization", "source": "o", "enforcement": "active" }`) }) ctx := t.Context() _, _, err := client.Organizations.UpdateRepositoryRuleset(ctx, "o", 21, input) if err != nil { t.Errorf("Organizations.UpdateRepositoryRuleset returned error: %v", err) } } func TestOrganizationsService_UpdateRepositoryRuleset_OmitZero_EmptySlice(t *testing.T) { t.Parallel() client, mux, _ := setup(t) input := RepositoryRuleset{ Name: "test ruleset", Enforcement: RulesetEnforcementActive, BypassActors: []*BypassActor{}, } mux.HandleFunc("/orgs/o/rulesets/21", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "PUT") testJSONBody(t, r, input) fmt.Fprint(w, `{ "id": 21, "name": "test ruleset", "source_type": "Organization", "source": "o", "enforcement": "active", "bypass_actors": [] }`) }) ctx := t.Context() _, _, err := client.Organizations.UpdateRepositoryRuleset(ctx, "o", 21, input) if err != nil { t.Errorf("Organizations.UpdateRepositoryRuleset returned error: %v", err) } } func TestOrganizationsService_DeleteRepositoryRuleset(t *testing.T) { t.Parallel() client, mux, _ := setup(t) mux.HandleFunc("/orgs/o/rulesets/21", func(_ http.ResponseWriter, r *http.Request) { testMethod(t, r, "DELETE") }) ctx := t.Context() _, err := client.Organizations.DeleteRepositoryRuleset(ctx, "o", 21) if err != nil { t.Errorf("Organizations.DeleteRepositoryRuleset returned error: %v", err) } const methodName = "DeleteRepositoryRuleset" testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { return client.Organizations.DeleteRepositoryRuleset(ctx, "0", 21) }) }