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, &params); 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, &params); 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, &params); 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, &params); 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, &params); 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, &params); 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, &params); 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  }