github.com/google/go-github/v64@v64.0.0/github/repos_rules.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 "encoding/json" 11 "fmt" 12 ) 13 14 // BypassActor represents the bypass actors from a ruleset. 15 type BypassActor struct { 16 ActorID *int64 `json:"actor_id,omitempty"` 17 // Possible values for ActorType are: RepositoryRole, Team, Integration, OrganizationAdmin 18 ActorType *string `json:"actor_type,omitempty"` 19 // Possible values for BypassMode are: always, pull_request 20 BypassMode *string `json:"bypass_mode,omitempty"` 21 } 22 23 // RulesetLink represents a single link object from GitHub ruleset request _links. 24 type RulesetLink struct { 25 HRef *string `json:"href,omitempty"` 26 } 27 28 // RulesetLinks represents the "_links" object in a Ruleset. 29 type RulesetLinks struct { 30 Self *RulesetLink `json:"self,omitempty"` 31 } 32 33 // RulesetRefConditionParameters represents the conditions object for ref_names. 34 type RulesetRefConditionParameters struct { 35 Include []string `json:"include"` 36 Exclude []string `json:"exclude"` 37 } 38 39 // RulesetRepositoryNamesConditionParameters represents the conditions object for repository_names. 40 type RulesetRepositoryNamesConditionParameters struct { 41 Include []string `json:"include"` 42 Exclude []string `json:"exclude"` 43 Protected *bool `json:"protected,omitempty"` 44 } 45 46 // RulesetRepositoryIDsConditionParameters represents the conditions object for repository_ids. 47 type RulesetRepositoryIDsConditionParameters struct { 48 RepositoryIDs []int64 `json:"repository_ids,omitempty"` 49 } 50 51 // RulesetRepositoryPropertyTargetParameters represents a repository_property name and values to be used for targeting. 52 type RulesetRepositoryPropertyTargetParameters struct { 53 Name string `json:"name"` 54 Values []string `json:"property_values"` 55 } 56 57 // RulesetRepositoryPropertyConditionParameters represents the conditions object for repository_property. 58 type RulesetRepositoryPropertyConditionParameters struct { 59 Include []RulesetRepositoryPropertyTargetParameters `json:"include"` 60 Exclude []RulesetRepositoryPropertyTargetParameters `json:"exclude"` 61 } 62 63 // RulesetConditions represents the conditions object in a ruleset. 64 // Set either RepositoryName or RepositoryID or RepositoryProperty, not more than one. 65 type RulesetConditions struct { 66 RefName *RulesetRefConditionParameters `json:"ref_name,omitempty"` 67 RepositoryName *RulesetRepositoryNamesConditionParameters `json:"repository_name,omitempty"` 68 RepositoryID *RulesetRepositoryIDsConditionParameters `json:"repository_id,omitempty"` 69 RepositoryProperty *RulesetRepositoryPropertyConditionParameters `json:"repository_property,omitempty"` 70 } 71 72 // RulePatternParameters represents the rule pattern parameters. 73 type RulePatternParameters struct { 74 Name *string `json:"name,omitempty"` 75 // If Negate is true, the rule will fail if the pattern matches. 76 Negate *bool `json:"negate,omitempty"` 77 // Possible values for Operator are: starts_with, ends_with, contains, regex 78 Operator string `json:"operator"` 79 Pattern string `json:"pattern"` 80 } 81 82 // RuleFileParameters represents a list of file paths. 83 type RuleFileParameters struct { 84 RestrictedFilePaths *[]string `json:"restricted_file_paths"` 85 } 86 87 // UpdateAllowsFetchAndMergeRuleParameters represents the update rule parameters. 88 type UpdateAllowsFetchAndMergeRuleParameters struct { 89 UpdateAllowsFetchAndMerge bool `json:"update_allows_fetch_and_merge"` 90 } 91 92 // RequiredDeploymentEnvironmentsRuleParameters represents the required_deployments rule parameters. 93 type RequiredDeploymentEnvironmentsRuleParameters struct { 94 RequiredDeploymentEnvironments []string `json:"required_deployment_environments"` 95 } 96 97 // PullRequestRuleParameters represents the pull_request rule parameters. 98 type PullRequestRuleParameters struct { 99 DismissStaleReviewsOnPush bool `json:"dismiss_stale_reviews_on_push"` 100 RequireCodeOwnerReview bool `json:"require_code_owner_review"` 101 RequireLastPushApproval bool `json:"require_last_push_approval"` 102 RequiredApprovingReviewCount int `json:"required_approving_review_count"` 103 RequiredReviewThreadResolution bool `json:"required_review_thread_resolution"` 104 } 105 106 // RuleRequiredStatusChecks represents the RequiredStatusChecks for the RequiredStatusChecksRuleParameters object. 107 type RuleRequiredStatusChecks struct { 108 Context string `json:"context"` 109 IntegrationID *int64 `json:"integration_id,omitempty"` 110 } 111 112 // RequiredStatusChecksRuleParameters represents the required_status_checks rule parameters. 113 type RequiredStatusChecksRuleParameters struct { 114 RequiredStatusChecks []RuleRequiredStatusChecks `json:"required_status_checks"` 115 StrictRequiredStatusChecksPolicy bool `json:"strict_required_status_checks_policy"` 116 } 117 118 // RuleRequiredWorkflow represents the Workflow for the RequireWorkflowsRuleParameters object. 119 type RuleRequiredWorkflow struct { 120 Path string `json:"path"` 121 Ref *string `json:"ref,omitempty"` 122 RepositoryID *int64 `json:"repository_id,omitempty"` 123 Sha *string `json:"sha,omitempty"` 124 } 125 126 // RequiredWorkflowsRuleParameters represents the workflows rule parameters. 127 type RequiredWorkflowsRuleParameters struct { 128 RequiredWorkflows []*RuleRequiredWorkflow `json:"workflows"` 129 } 130 131 // RepositoryRule represents a GitHub Rule. 132 type RepositoryRule struct { 133 Type string `json:"type"` 134 Parameters *json.RawMessage `json:"parameters,omitempty"` 135 RulesetSourceType string `json:"ruleset_source_type"` 136 RulesetSource string `json:"ruleset_source"` 137 RulesetID int64 `json:"ruleset_id"` 138 } 139 140 // UnmarshalJSON implements the json.Unmarshaler interface. 141 // This helps us handle the fact that RepositoryRule parameter field can be of numerous types. 142 func (r *RepositoryRule) UnmarshalJSON(data []byte) error { 143 type rule RepositoryRule 144 var RepositoryRule rule 145 if err := json.Unmarshal(data, &RepositoryRule); err != nil { 146 return err 147 } 148 149 r.RulesetID = RepositoryRule.RulesetID 150 r.RulesetSourceType = RepositoryRule.RulesetSourceType 151 r.RulesetSource = RepositoryRule.RulesetSource 152 r.Type = RepositoryRule.Type 153 154 switch RepositoryRule.Type { 155 case "creation", "deletion", "merge_queue", "non_fast_forward", "required_linear_history", "required_signatures": 156 r.Parameters = nil 157 case "update": 158 if RepositoryRule.Parameters == nil { 159 r.Parameters = nil 160 return nil 161 } 162 params := UpdateAllowsFetchAndMergeRuleParameters{} 163 if err := json.Unmarshal(*RepositoryRule.Parameters, ¶ms); err != nil { 164 return err 165 } 166 167 bytes, _ := json.Marshal(params) 168 rawParams := json.RawMessage(bytes) 169 170 r.Parameters = &rawParams 171 172 case "required_deployments": 173 params := RequiredDeploymentEnvironmentsRuleParameters{} 174 if err := json.Unmarshal(*RepositoryRule.Parameters, ¶ms); err != nil { 175 return err 176 } 177 178 bytes, _ := json.Marshal(params) 179 rawParams := json.RawMessage(bytes) 180 181 r.Parameters = &rawParams 182 case "commit_message_pattern", "commit_author_email_pattern", "committer_email_pattern", "branch_name_pattern", "tag_name_pattern": 183 params := RulePatternParameters{} 184 if err := json.Unmarshal(*RepositoryRule.Parameters, ¶ms); err != nil { 185 return err 186 } 187 188 bytes, _ := json.Marshal(params) 189 rawParams := json.RawMessage(bytes) 190 191 r.Parameters = &rawParams 192 case "pull_request": 193 params := PullRequestRuleParameters{} 194 if err := json.Unmarshal(*RepositoryRule.Parameters, ¶ms); err != nil { 195 return err 196 } 197 198 bytes, _ := json.Marshal(params) 199 rawParams := json.RawMessage(bytes) 200 201 r.Parameters = &rawParams 202 case "required_status_checks": 203 params := RequiredStatusChecksRuleParameters{} 204 if err := json.Unmarshal(*RepositoryRule.Parameters, ¶ms); err != nil { 205 return err 206 } 207 208 bytes, _ := json.Marshal(params) 209 rawParams := json.RawMessage(bytes) 210 211 r.Parameters = &rawParams 212 case "workflows": 213 params := RequiredWorkflowsRuleParameters{} 214 if err := json.Unmarshal(*RepositoryRule.Parameters, ¶ms); err != nil { 215 return err 216 } 217 218 bytes, _ := json.Marshal(params) 219 rawParams := json.RawMessage(bytes) 220 221 r.Parameters = &rawParams 222 case "file_path_restriction": 223 params := RuleFileParameters{} 224 if err := json.Unmarshal(*RepositoryRule.Parameters, ¶ms); err != nil { 225 return err 226 } 227 bytes, _ := json.Marshal(params) 228 rawParams := json.RawMessage(bytes) 229 230 r.Parameters = &rawParams 231 default: 232 r.Type = "" 233 r.Parameters = nil 234 return fmt.Errorf("RepositoryRule.Type %q is not yet implemented, unable to unmarshal (%#v)", RepositoryRule.Type, RepositoryRule) 235 } 236 237 return nil 238 } 239 240 // NewMergeQueueRule creates a rule to only allow merges via a merge queue. 241 func NewMergeQueueRule() (rule *RepositoryRule) { 242 return &RepositoryRule{ 243 Type: "merge_queue", 244 } 245 } 246 247 // NewCreationRule creates a rule to only allow users with bypass permission to create matching refs. 248 func NewCreationRule() (rule *RepositoryRule) { 249 return &RepositoryRule{ 250 Type: "creation", 251 } 252 } 253 254 // NewUpdateRule creates a rule to only allow users with bypass permission to update matching refs. 255 func NewUpdateRule(params *UpdateAllowsFetchAndMergeRuleParameters) (rule *RepositoryRule) { 256 if params != nil { 257 bytes, _ := json.Marshal(params) 258 259 rawParams := json.RawMessage(bytes) 260 261 return &RepositoryRule{ 262 Type: "update", 263 Parameters: &rawParams, 264 } 265 } 266 return &RepositoryRule{ 267 Type: "update", 268 } 269 } 270 271 // NewDeletionRule creates a rule to only allow users with bypass permissions to delete matching refs. 272 func NewDeletionRule() (rule *RepositoryRule) { 273 return &RepositoryRule{ 274 Type: "deletion", 275 } 276 } 277 278 // NewRequiredLinearHistoryRule creates a rule to prevent merge commits from being pushed to matching branches. 279 func NewRequiredLinearHistoryRule() (rule *RepositoryRule) { 280 return &RepositoryRule{ 281 Type: "required_linear_history", 282 } 283 } 284 285 // NewRequiredDeploymentsRule creates a rule to require environments to be successfully deployed before they can be merged into the matching branches. 286 func NewRequiredDeploymentsRule(params *RequiredDeploymentEnvironmentsRuleParameters) (rule *RepositoryRule) { 287 bytes, _ := json.Marshal(params) 288 289 rawParams := json.RawMessage(bytes) 290 291 return &RepositoryRule{ 292 Type: "required_deployments", 293 Parameters: &rawParams, 294 } 295 } 296 297 // NewRequiredSignaturesRule creates a rule a to require commits pushed to matching branches to have verified signatures. 298 func NewRequiredSignaturesRule() (rule *RepositoryRule) { 299 return &RepositoryRule{ 300 Type: "required_signatures", 301 } 302 } 303 304 // NewPullRequestRule creates a rule to require all commits be made to a non-target branch and submitted via a pull request before they can be merged. 305 func NewPullRequestRule(params *PullRequestRuleParameters) (rule *RepositoryRule) { 306 bytes, _ := json.Marshal(params) 307 308 rawParams := json.RawMessage(bytes) 309 310 return &RepositoryRule{ 311 Type: "pull_request", 312 Parameters: &rawParams, 313 } 314 } 315 316 // NewRequiredStatusChecksRule creates a rule to require which status checks must pass before branches can be merged into a branch rule. 317 func NewRequiredStatusChecksRule(params *RequiredStatusChecksRuleParameters) (rule *RepositoryRule) { 318 bytes, _ := json.Marshal(params) 319 320 rawParams := json.RawMessage(bytes) 321 322 return &RepositoryRule{ 323 Type: "required_status_checks", 324 Parameters: &rawParams, 325 } 326 } 327 328 // NewNonFastForwardRule creates a rule as part to prevent users with push access from force pushing to matching branches. 329 func NewNonFastForwardRule() (rule *RepositoryRule) { 330 return &RepositoryRule{ 331 Type: "non_fast_forward", 332 } 333 } 334 335 // NewCommitMessagePatternRule creates a rule to restrict commit message patterns being pushed to matching branches. 336 func NewCommitMessagePatternRule(params *RulePatternParameters) (rule *RepositoryRule) { 337 bytes, _ := json.Marshal(params) 338 339 rawParams := json.RawMessage(bytes) 340 341 return &RepositoryRule{ 342 Type: "commit_message_pattern", 343 Parameters: &rawParams, 344 } 345 } 346 347 // NewCommitAuthorEmailPatternRule creates a rule to restrict commits with author email patterns being merged into matching branches. 348 func NewCommitAuthorEmailPatternRule(params *RulePatternParameters) (rule *RepositoryRule) { 349 bytes, _ := json.Marshal(params) 350 351 rawParams := json.RawMessage(bytes) 352 353 return &RepositoryRule{ 354 Type: "commit_author_email_pattern", 355 Parameters: &rawParams, 356 } 357 } 358 359 // NewCommitterEmailPatternRule creates a rule to restrict commits with committer email patterns being merged into matching branches. 360 func NewCommitterEmailPatternRule(params *RulePatternParameters) (rule *RepositoryRule) { 361 bytes, _ := json.Marshal(params) 362 363 rawParams := json.RawMessage(bytes) 364 365 return &RepositoryRule{ 366 Type: "committer_email_pattern", 367 Parameters: &rawParams, 368 } 369 } 370 371 // NewBranchNamePatternRule creates a rule to restrict branch patterns from being merged into matching branches. 372 func NewBranchNamePatternRule(params *RulePatternParameters) (rule *RepositoryRule) { 373 bytes, _ := json.Marshal(params) 374 375 rawParams := json.RawMessage(bytes) 376 377 return &RepositoryRule{ 378 Type: "branch_name_pattern", 379 Parameters: &rawParams, 380 } 381 } 382 383 // NewTagNamePatternRule creates a rule to restrict tag patterns contained in non-target branches from being merged into matching branches. 384 func NewTagNamePatternRule(params *RulePatternParameters) (rule *RepositoryRule) { 385 bytes, _ := json.Marshal(params) 386 387 rawParams := json.RawMessage(bytes) 388 389 return &RepositoryRule{ 390 Type: "tag_name_pattern", 391 Parameters: &rawParams, 392 } 393 } 394 395 // NewRequiredWorkflowsRule creates a rule to require which status checks must pass before branches can be merged into a branch rule. 396 func NewRequiredWorkflowsRule(params *RequiredWorkflowsRuleParameters) (rule *RepositoryRule) { 397 bytes, _ := json.Marshal(params) 398 399 rawParams := json.RawMessage(bytes) 400 401 return &RepositoryRule{ 402 Type: "workflows", 403 Parameters: &rawParams, 404 } 405 } 406 407 // NewFilePathRestrictionRule creates a rule to restrict file paths from being pushed to. 408 func NewFilePathRestrictionRule(params *RuleFileParameters) (rule *RepositoryRule) { 409 bytes, _ := json.Marshal(params) 410 411 rawParams := json.RawMessage(bytes) 412 413 return &RepositoryRule{ 414 Type: "file_path_restriction", 415 Parameters: &rawParams, 416 } 417 } 418 419 // Ruleset represents a GitHub ruleset object. 420 type Ruleset struct { 421 ID *int64 `json:"id,omitempty"` 422 Name string `json:"name"` 423 // Possible values for Target are branch, tag 424 Target *string `json:"target,omitempty"` 425 // Possible values for SourceType are: Repository, Organization 426 SourceType *string `json:"source_type,omitempty"` 427 Source string `json:"source"` 428 // Possible values for Enforcement are: disabled, active, evaluate 429 Enforcement string `json:"enforcement"` 430 BypassActors []*BypassActor `json:"bypass_actors,omitempty"` 431 NodeID *string `json:"node_id,omitempty"` 432 Links *RulesetLinks `json:"_links,omitempty"` 433 Conditions *RulesetConditions `json:"conditions,omitempty"` 434 Rules []*RepositoryRule `json:"rules,omitempty"` 435 } 436 437 // rulesetNoOmitBypassActors represents a GitHub ruleset object. The struct does not omit bypassActors if the field is nil or an empty array is passed. 438 type rulesetNoOmitBypassActors struct { 439 ID *int64 `json:"id,omitempty"` 440 Name string `json:"name"` 441 // Possible values for Target are branch, tag 442 Target *string `json:"target,omitempty"` 443 // Possible values for SourceType are: Repository, Organization 444 SourceType *string `json:"source_type,omitempty"` 445 Source string `json:"source"` 446 // Possible values for Enforcement are: disabled, active, evaluate 447 Enforcement string `json:"enforcement"` 448 BypassActors []*BypassActor `json:"bypass_actors"` 449 NodeID *string `json:"node_id,omitempty"` 450 Links *RulesetLinks `json:"_links,omitempty"` 451 Conditions *RulesetConditions `json:"conditions,omitempty"` 452 Rules []*RepositoryRule `json:"rules,omitempty"` 453 } 454 455 // GetRulesForBranch gets all the rules that apply to the specified branch. 456 // 457 // GitHub API docs: https://docs.github.com/rest/repos/rules#get-rules-for-a-branch 458 // 459 //meta:operation GET /repos/{owner}/{repo}/rules/branches/{branch} 460 func (s *RepositoriesService) GetRulesForBranch(ctx context.Context, owner, repo, branch string) ([]*RepositoryRule, *Response, error) { 461 u := fmt.Sprintf("repos/%v/%v/rules/branches/%v", owner, repo, branch) 462 463 req, err := s.client.NewRequest("GET", u, nil) 464 if err != nil { 465 return nil, nil, err 466 } 467 468 var rules []*RepositoryRule 469 resp, err := s.client.Do(ctx, req, &rules) 470 if err != nil { 471 return nil, resp, err 472 } 473 474 return rules, resp, nil 475 } 476 477 // GetAllRulesets gets all the rules that apply to the specified repository. 478 // If includesParents is true, rulesets configured at the organization level that apply to the repository will be returned. 479 // 480 // GitHub API docs: https://docs.github.com/rest/repos/rules#get-all-repository-rulesets 481 // 482 //meta:operation GET /repos/{owner}/{repo}/rulesets 483 func (s *RepositoriesService) GetAllRulesets(ctx context.Context, owner, repo string, includesParents bool) ([]*Ruleset, *Response, error) { 484 u := fmt.Sprintf("repos/%v/%v/rulesets?includes_parents=%v", owner, repo, includesParents) 485 486 req, err := s.client.NewRequest("GET", u, nil) 487 if err != nil { 488 return nil, nil, err 489 } 490 491 var ruleset []*Ruleset 492 resp, err := s.client.Do(ctx, req, &ruleset) 493 if err != nil { 494 return nil, resp, err 495 } 496 497 return ruleset, resp, nil 498 } 499 500 // CreateRuleset creates a ruleset for the specified repository. 501 // 502 // GitHub API docs: https://docs.github.com/rest/repos/rules#create-a-repository-ruleset 503 // 504 //meta:operation POST /repos/{owner}/{repo}/rulesets 505 func (s *RepositoriesService) CreateRuleset(ctx context.Context, owner, repo string, rs *Ruleset) (*Ruleset, *Response, error) { 506 u := fmt.Sprintf("repos/%v/%v/rulesets", owner, repo) 507 508 req, err := s.client.NewRequest("POST", u, rs) 509 if err != nil { 510 return nil, nil, err 511 } 512 513 var ruleset *Ruleset 514 resp, err := s.client.Do(ctx, req, &ruleset) 515 if err != nil { 516 return nil, resp, err 517 } 518 519 return ruleset, resp, nil 520 } 521 522 // GetRuleset gets a ruleset for the specified repository. 523 // If includesParents is true, rulesets configured at the organization level that apply to the repository will be returned. 524 // 525 // GitHub API docs: https://docs.github.com/rest/repos/rules#get-a-repository-ruleset 526 // 527 //meta:operation GET /repos/{owner}/{repo}/rulesets/{ruleset_id} 528 func (s *RepositoriesService) GetRuleset(ctx context.Context, owner, repo string, rulesetID int64, includesParents bool) (*Ruleset, *Response, error) { 529 u := fmt.Sprintf("repos/%v/%v/rulesets/%v?includes_parents=%v", owner, repo, rulesetID, includesParents) 530 531 req, err := s.client.NewRequest("GET", u, nil) 532 if err != nil { 533 return nil, nil, err 534 } 535 536 var ruleset *Ruleset 537 resp, err := s.client.Do(ctx, req, &ruleset) 538 if err != nil { 539 return nil, resp, err 540 } 541 542 return ruleset, resp, nil 543 } 544 545 // UpdateRuleset updates a ruleset for the specified repository. 546 // 547 // GitHub API docs: https://docs.github.com/rest/repos/rules#update-a-repository-ruleset 548 // 549 //meta:operation PUT /repos/{owner}/{repo}/rulesets/{ruleset_id} 550 func (s *RepositoriesService) UpdateRuleset(ctx context.Context, owner, repo string, rulesetID int64, rs *Ruleset) (*Ruleset, *Response, error) { 551 u := fmt.Sprintf("repos/%v/%v/rulesets/%v", owner, repo, rulesetID) 552 553 req, err := s.client.NewRequest("PUT", u, rs) 554 if err != nil { 555 return nil, nil, err 556 } 557 558 var ruleset *Ruleset 559 resp, err := s.client.Do(ctx, req, &ruleset) 560 if err != nil { 561 return nil, resp, err 562 } 563 564 return ruleset, resp, nil 565 } 566 567 // UpdateRulesetNoBypassActor updates a ruleset for the specified repository. 568 // 569 // This function is necessary as the UpdateRuleset function does not marshal ByPassActor if passed as nil or an empty array. 570 // 571 // GitHub API docs: https://docs.github.com/rest/repos/rules#update-a-repository-ruleset 572 // 573 //meta:operation PUT /repos/{owner}/{repo}/rulesets/{ruleset_id} 574 func (s *RepositoriesService) UpdateRulesetNoBypassActor(ctx context.Context, owner, repo string, rulesetID int64, rs *Ruleset) (*Ruleset, *Response, error) { 575 u := fmt.Sprintf("repos/%v/%v/rulesets/%v", owner, repo, rulesetID) 576 577 rsNoBypassActor := &rulesetNoOmitBypassActors{} 578 579 if rs != nil { 580 rsNoBypassActor = &rulesetNoOmitBypassActors{ 581 ID: rs.ID, 582 Name: rs.Name, 583 Target: rs.Target, 584 SourceType: rs.SourceType, 585 Source: rs.Source, 586 Enforcement: rs.Enforcement, 587 BypassActors: rs.BypassActors, 588 NodeID: rs.NodeID, 589 Links: rs.Links, 590 Conditions: rs.Conditions, 591 Rules: rs.Rules, 592 } 593 } 594 595 req, err := s.client.NewRequest("PUT", u, rsNoBypassActor) 596 if err != nil { 597 return nil, nil, err 598 } 599 600 var ruleSet *Ruleset 601 resp, err := s.client.Do(ctx, req, &ruleSet) 602 if err != nil { 603 return nil, resp, err 604 } 605 606 return ruleSet, resp, nil 607 } 608 609 // DeleteRuleset deletes a ruleset for the specified repository. 610 // 611 // GitHub API docs: https://docs.github.com/rest/repos/rules#delete-a-repository-ruleset 612 // 613 //meta:operation DELETE /repos/{owner}/{repo}/rulesets/{ruleset_id} 614 func (s *RepositoriesService) DeleteRuleset(ctx context.Context, owner, repo string, rulesetID int64) (*Response, error) { 615 u := fmt.Sprintf("repos/%v/%v/rulesets/%v", owner, repo, rulesetID) 616 617 req, err := s.client.NewRequest("DELETE", u, nil) 618 if err != nil { 619 return nil, err 620 } 621 622 return s.client.Do(ctx, req, nil) 623 }