...

Source file src/github.com/google/go-github/v55/github/repos_rules.go

Documentation: github.com/google/go-github/v55/github

     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  // RulesetCondition represents the conditions object in a ruleset.
    52  // Set either RepositoryName or RepositoryID, not both.
    53  type RulesetConditions struct {
    54  	RefName        *RulesetRefConditionParameters             `json:"ref_name,omitempty"`
    55  	RepositoryName *RulesetRepositoryNamesConditionParameters `json:"repository_name,omitempty"`
    56  	RepositoryID   *RulesetRepositoryIDsConditionParameters   `json:"repository_id,omitempty"`
    57  }
    58  
    59  // RulePatternParameters represents the rule pattern parameters.
    60  type RulePatternParameters struct {
    61  	Name *string `json:"name,omitempty"`
    62  	// If Negate is true, the rule will fail if the pattern matches.
    63  	Negate *bool `json:"negate,omitempty"`
    64  	// Possible values for Operator are: starts_with, ends_with, contains, regex
    65  	Operator string `json:"operator"`
    66  	Pattern  string `json:"pattern"`
    67  }
    68  
    69  // UpdateAllowsFetchAndMergeRuleParameters represents the update rule parameters.
    70  type UpdateAllowsFetchAndMergeRuleParameters struct {
    71  	UpdateAllowsFetchAndMerge bool `json:"update_allows_fetch_and_merge"`
    72  }
    73  
    74  // RequiredDeploymentEnvironmentsRuleParameters represents the required_deployments rule parameters.
    75  type RequiredDeploymentEnvironmentsRuleParameters struct {
    76  	RequiredDeploymentEnvironments []string `json:"required_deployment_environments"`
    77  }
    78  
    79  // PullRequestRuleParameters represents the pull_request rule parameters.
    80  type PullRequestRuleParameters struct {
    81  	DismissStaleReviewsOnPush      bool `json:"dismiss_stale_reviews_on_push"`
    82  	RequireCodeOwnerReview         bool `json:"require_code_owner_review"`
    83  	RequireLastPushApproval        bool `json:"require_last_push_approval"`
    84  	RequiredApprovingReviewCount   int  `json:"required_approving_review_count"`
    85  	RequiredReviewThreadResolution bool `json:"required_review_thread_resolution"`
    86  }
    87  
    88  // RuleRequiredStatusChecks represents the RequiredStatusChecks for the RequiredStatusChecksRuleParameters object.
    89  type RuleRequiredStatusChecks struct {
    90  	Context       string `json:"context"`
    91  	IntegrationID *int64 `json:"integration_id,omitempty"`
    92  }
    93  
    94  // RequiredStatusChecksRuleParameters represents the required_status_checks rule parameters.
    95  type RequiredStatusChecksRuleParameters struct {
    96  	RequiredStatusChecks             []RuleRequiredStatusChecks `json:"required_status_checks"`
    97  	StrictRequiredStatusChecksPolicy bool                       `json:"strict_required_status_checks_policy"`
    98  }
    99  
   100  // RepositoryRule represents a GitHub Rule.
   101  type RepositoryRule struct {
   102  	Type       string           `json:"type"`
   103  	Parameters *json.RawMessage `json:"parameters,omitempty"`
   104  }
   105  
   106  // UnmarshalJSON implements the json.Unmarshaler interface.
   107  // This helps us handle the fact that RepositoryRule parameter field can be of numerous types.
   108  func (r *RepositoryRule) UnmarshalJSON(data []byte) error {
   109  	type rule RepositoryRule
   110  	var RepositoryRule rule
   111  	if err := json.Unmarshal(data, &RepositoryRule); err != nil {
   112  		return err
   113  	}
   114  
   115  	r.Type = RepositoryRule.Type
   116  
   117  	switch RepositoryRule.Type {
   118  	case "creation", "deletion", "required_linear_history", "required_signatures", "non_fast_forward":
   119  		r.Parameters = nil
   120  	case "update":
   121  		if RepositoryRule.Parameters == nil {
   122  			r.Parameters = nil
   123  			return nil
   124  		}
   125  		params := UpdateAllowsFetchAndMergeRuleParameters{}
   126  		if err := json.Unmarshal(*RepositoryRule.Parameters, &params); err != nil {
   127  			return err
   128  		}
   129  
   130  		bytes, _ := json.Marshal(params)
   131  		rawParams := json.RawMessage(bytes)
   132  
   133  		r.Parameters = &rawParams
   134  
   135  	case "required_deployments":
   136  		params := RequiredDeploymentEnvironmentsRuleParameters{}
   137  		if err := json.Unmarshal(*RepositoryRule.Parameters, &params); err != nil {
   138  			return err
   139  		}
   140  
   141  		bytes, _ := json.Marshal(params)
   142  		rawParams := json.RawMessage(bytes)
   143  
   144  		r.Parameters = &rawParams
   145  	case "commit_message_pattern", "commit_author_email_pattern", "committer_email_pattern", "branch_name_pattern", "tag_name_pattern":
   146  		params := RulePatternParameters{}
   147  		if err := json.Unmarshal(*RepositoryRule.Parameters, &params); err != nil {
   148  			return err
   149  		}
   150  
   151  		bytes, _ := json.Marshal(params)
   152  		rawParams := json.RawMessage(bytes)
   153  
   154  		r.Parameters = &rawParams
   155  	case "pull_request":
   156  		params := PullRequestRuleParameters{}
   157  		if err := json.Unmarshal(*RepositoryRule.Parameters, &params); err != nil {
   158  			return err
   159  		}
   160  
   161  		bytes, _ := json.Marshal(params)
   162  		rawParams := json.RawMessage(bytes)
   163  
   164  		r.Parameters = &rawParams
   165  	case "required_status_checks":
   166  		params := RequiredStatusChecksRuleParameters{}
   167  		if err := json.Unmarshal(*RepositoryRule.Parameters, &params); err != nil {
   168  			return err
   169  		}
   170  
   171  		bytes, _ := json.Marshal(params)
   172  		rawParams := json.RawMessage(bytes)
   173  
   174  		r.Parameters = &rawParams
   175  	default:
   176  		r.Type = ""
   177  		r.Parameters = nil
   178  		return fmt.Errorf("RepositoryRule.Type %T is not yet implemented, unable to unmarshal", RepositoryRule.Type)
   179  	}
   180  
   181  	return nil
   182  }
   183  
   184  // NewCreationRule creates a rule to only allow users with bypass permission to create matching refs.
   185  func NewCreationRule() (rule *RepositoryRule) {
   186  	return &RepositoryRule{
   187  		Type: "creation",
   188  	}
   189  }
   190  
   191  // NewUpdateRule creates a rule to only allow users with bypass permission to update matching refs.
   192  func NewUpdateRule(params *UpdateAllowsFetchAndMergeRuleParameters) (rule *RepositoryRule) {
   193  	if params != nil {
   194  		bytes, _ := json.Marshal(params)
   195  
   196  		rawParams := json.RawMessage(bytes)
   197  
   198  		return &RepositoryRule{
   199  			Type:       "update",
   200  			Parameters: &rawParams,
   201  		}
   202  	}
   203  	return &RepositoryRule{
   204  		Type: "update",
   205  	}
   206  }
   207  
   208  // NewDeletionRule creates a rule to only allow users with bypass permissions to delete matching refs.
   209  func NewDeletionRule() (rule *RepositoryRule) {
   210  	return &RepositoryRule{
   211  		Type: "deletion",
   212  	}
   213  }
   214  
   215  // NewRequiredLinearHistoryRule creates a rule to prevent merge commits from being pushed to matching branches.
   216  func NewRequiredLinearHistoryRule() (rule *RepositoryRule) {
   217  	return &RepositoryRule{
   218  		Type: "required_linear_history",
   219  	}
   220  }
   221  
   222  // NewRequiredDeploymentsRule creates a rule to require environments to be successfully deployed before they can be merged into the matching branches.
   223  func NewRequiredDeploymentsRule(params *RequiredDeploymentEnvironmentsRuleParameters) (rule *RepositoryRule) {
   224  	bytes, _ := json.Marshal(params)
   225  
   226  	rawParams := json.RawMessage(bytes)
   227  
   228  	return &RepositoryRule{
   229  		Type:       "required_deployments",
   230  		Parameters: &rawParams,
   231  	}
   232  }
   233  
   234  // NewRequiredSignaturesRule creates a rule a to require commits pushed to matching branches to have verified signatures.
   235  func NewRequiredSignaturesRule() (rule *RepositoryRule) {
   236  	return &RepositoryRule{
   237  		Type: "required_signatures",
   238  	}
   239  }
   240  
   241  // 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.
   242  func NewPullRequestRule(params *PullRequestRuleParameters) (rule *RepositoryRule) {
   243  	bytes, _ := json.Marshal(params)
   244  
   245  	rawParams := json.RawMessage(bytes)
   246  
   247  	return &RepositoryRule{
   248  		Type:       "pull_request",
   249  		Parameters: &rawParams,
   250  	}
   251  }
   252  
   253  // NewRequiredStatusChecksRule creates a rule to require which status checks must pass before branches can be merged into a branch rule.
   254  func NewRequiredStatusChecksRule(params *RequiredStatusChecksRuleParameters) (rule *RepositoryRule) {
   255  	bytes, _ := json.Marshal(params)
   256  
   257  	rawParams := json.RawMessage(bytes)
   258  
   259  	return &RepositoryRule{
   260  		Type:       "required_status_checks",
   261  		Parameters: &rawParams,
   262  	}
   263  }
   264  
   265  // NewNonFastForwardRule creates a rule as part to prevent users with push access from force pushing to matching branches.
   266  func NewNonFastForwardRule() (rule *RepositoryRule) {
   267  	return &RepositoryRule{
   268  		Type: "non_fast_forward",
   269  	}
   270  }
   271  
   272  // NewCommitMessagePatternRule creates a rule to restrict commit message patterns being pushed to matching branches.
   273  func NewCommitMessagePatternRule(params *RulePatternParameters) (rule *RepositoryRule) {
   274  	bytes, _ := json.Marshal(params)
   275  
   276  	rawParams := json.RawMessage(bytes)
   277  
   278  	return &RepositoryRule{
   279  		Type:       "commit_message_pattern",
   280  		Parameters: &rawParams,
   281  	}
   282  }
   283  
   284  // NewCommitAuthorEmailPatternRule creates a rule to restrict commits with author email patterns being merged into matching branches.
   285  func NewCommitAuthorEmailPatternRule(params *RulePatternParameters) (rule *RepositoryRule) {
   286  	bytes, _ := json.Marshal(params)
   287  
   288  	rawParams := json.RawMessage(bytes)
   289  
   290  	return &RepositoryRule{
   291  		Type:       "commit_author_email_pattern",
   292  		Parameters: &rawParams,
   293  	}
   294  }
   295  
   296  // NewCommitterEmailPatternRule creates a rule to restrict commits with committer email patterns being merged into matching branches.
   297  func NewCommitterEmailPatternRule(params *RulePatternParameters) (rule *RepositoryRule) {
   298  	bytes, _ := json.Marshal(params)
   299  
   300  	rawParams := json.RawMessage(bytes)
   301  
   302  	return &RepositoryRule{
   303  		Type:       "committer_email_pattern",
   304  		Parameters: &rawParams,
   305  	}
   306  }
   307  
   308  // NewBranchNamePatternRule creates a rule to restrict branch patterns from being merged into matching branches.
   309  func NewBranchNamePatternRule(params *RulePatternParameters) (rule *RepositoryRule) {
   310  	bytes, _ := json.Marshal(params)
   311  
   312  	rawParams := json.RawMessage(bytes)
   313  
   314  	return &RepositoryRule{
   315  		Type:       "branch_name_pattern",
   316  		Parameters: &rawParams,
   317  	}
   318  }
   319  
   320  // NewTagNamePatternRule creates a rule to restrict tag patterns contained in non-target branches from being merged into matching branches.
   321  func NewTagNamePatternRule(params *RulePatternParameters) (rule *RepositoryRule) {
   322  	bytes, _ := json.Marshal(params)
   323  
   324  	rawParams := json.RawMessage(bytes)
   325  
   326  	return &RepositoryRule{
   327  		Type:       "tag_name_pattern",
   328  		Parameters: &rawParams,
   329  	}
   330  }
   331  
   332  // Ruleset represents a GitHub ruleset object.
   333  type Ruleset struct {
   334  	ID   *int64 `json:"id,omitempty"`
   335  	Name string `json:"name"`
   336  	// Possible values for Target are branch, tag
   337  	Target *string `json:"target,omitempty"`
   338  	// Possible values for SourceType are: Repository, Organization
   339  	SourceType *string `json:"source_type,omitempty"`
   340  	Source     string  `json:"source"`
   341  	// Possible values for Enforcement are: disabled, active, evaluate
   342  	Enforcement  string             `json:"enforcement"`
   343  	BypassActors []*BypassActor     `json:"bypass_actors,omitempty"`
   344  	NodeID       *string            `json:"node_id,omitempty"`
   345  	Links        *RulesetLinks      `json:"_links,omitempty"`
   346  	Conditions   *RulesetConditions `json:"conditions,omitempty"`
   347  	Rules        []*RepositoryRule  `json:"rules,omitempty"`
   348  }
   349  
   350  // GetRulesForBranch gets all the rules that apply to the specified branch.
   351  //
   352  // GitHub API docs: https://docs.github.com/en/rest/repos/rules#get-rules-for-a-branch
   353  func (s *RepositoriesService) GetRulesForBranch(ctx context.Context, owner, repo, branch string) ([]*RepositoryRule, *Response, error) {
   354  	u := fmt.Sprintf("repos/%v/%v/rules/branches/%v", owner, repo, branch)
   355  
   356  	req, err := s.client.NewRequest("GET", u, nil)
   357  	if err != nil {
   358  		return nil, nil, err
   359  	}
   360  
   361  	var rules []*RepositoryRule
   362  	resp, err := s.client.Do(ctx, req, &rules)
   363  	if err != nil {
   364  		return nil, resp, err
   365  	}
   366  
   367  	return rules, resp, nil
   368  }
   369  
   370  // GetAllRulesets gets all the rules that apply to the specified repository.
   371  // If includesParents is true, rulesets configured at the organization level that apply to the repository will be returned.
   372  //
   373  // GitHub API docs: https://docs.github.com/en/rest/repos/rules#get-all-repository-rulesets
   374  func (s *RepositoriesService) GetAllRulesets(ctx context.Context, owner, repo string, includesParents bool) ([]*Ruleset, *Response, error) {
   375  	u := fmt.Sprintf("repos/%v/%v/rulesets?includes_parents=%v", owner, repo, includesParents)
   376  
   377  	req, err := s.client.NewRequest("GET", u, nil)
   378  	if err != nil {
   379  		return nil, nil, err
   380  	}
   381  
   382  	var ruleset []*Ruleset
   383  	resp, err := s.client.Do(ctx, req, &ruleset)
   384  	if err != nil {
   385  		return nil, resp, err
   386  	}
   387  
   388  	return ruleset, resp, nil
   389  }
   390  
   391  // CreateRuleset creates a ruleset for the specified repository.
   392  //
   393  // GitHub API docs: https://docs.github.com/en/rest/repos/rules#create-a-repository-ruleset
   394  func (s *RepositoriesService) CreateRuleset(ctx context.Context, owner, repo string, rs *Ruleset) (*Ruleset, *Response, error) {
   395  	u := fmt.Sprintf("repos/%v/%v/rulesets", owner, repo)
   396  
   397  	req, err := s.client.NewRequest("POST", u, rs)
   398  	if err != nil {
   399  		return nil, nil, err
   400  	}
   401  
   402  	var ruleset *Ruleset
   403  	resp, err := s.client.Do(ctx, req, &ruleset)
   404  	if err != nil {
   405  		return nil, resp, err
   406  	}
   407  
   408  	return ruleset, resp, nil
   409  }
   410  
   411  // GetRuleset gets a ruleset for the specified repository.
   412  // If includesParents is true, rulesets configured at the organization level that apply to the repository will be returned.
   413  //
   414  // GitHub API docs: https://docs.github.com/en/rest/repos/rules#get-a-repository-ruleset
   415  func (s *RepositoriesService) GetRuleset(ctx context.Context, owner, repo string, rulesetID int64, includesParents bool) (*Ruleset, *Response, error) {
   416  	u := fmt.Sprintf("repos/%v/%v/rulesets/%v?includes_parents=%v", owner, repo, rulesetID, includesParents)
   417  
   418  	req, err := s.client.NewRequest("GET", u, nil)
   419  	if err != nil {
   420  		return nil, nil, err
   421  	}
   422  
   423  	var ruleset *Ruleset
   424  	resp, err := s.client.Do(ctx, req, &ruleset)
   425  	if err != nil {
   426  		return nil, resp, err
   427  	}
   428  
   429  	return ruleset, resp, nil
   430  }
   431  
   432  // UpdateRuleset updates a ruleset for the specified repository.
   433  //
   434  // GitHub API docs: https://docs.github.com/en/rest/repos/rules#update-a-repository-ruleset
   435  func (s *RepositoriesService) UpdateRuleset(ctx context.Context, owner, repo string, rulesetID int64, rs *Ruleset) (*Ruleset, *Response, error) {
   436  	u := fmt.Sprintf("repos/%v/%v/rulesets/%v", owner, repo, rulesetID)
   437  
   438  	req, err := s.client.NewRequest("PUT", u, rs)
   439  	if err != nil {
   440  		return nil, nil, err
   441  	}
   442  
   443  	var ruleset *Ruleset
   444  	resp, err := s.client.Do(ctx, req, &ruleset)
   445  	if err != nil {
   446  		return nil, resp, err
   447  	}
   448  
   449  	return ruleset, resp, nil
   450  }
   451  
   452  // DeleteRuleset deletes a ruleset for the specified repository.
   453  //
   454  // GitHub API docs: https://docs.github.com/en/rest/repos/rules#delete-a-repository-ruleset
   455  func (s *RepositoriesService) DeleteRuleset(ctx context.Context, owner, repo string, rulesetID int64) (*Response, error) {
   456  	u := fmt.Sprintf("repos/%v/%v/rulesets/%v", owner, repo, rulesetID)
   457  
   458  	req, err := s.client.NewRequest("DELETE", u, nil)
   459  	if err != nil {
   460  		return nil, err
   461  	}
   462  
   463  	return s.client.Do(ctx, req, nil)
   464  }
   465  

View as plain text