From 2204dce82bbe1d8663c1dcbae8ee91175397bf55 Mon Sep 17 00:00:00 2001 From: Matthew William Reidy <48036844+Matthew-Reidy@users.noreply.github.com> Date: Tue, 9 Jul 2024 11:27:08 -0700 Subject: [PATCH] Allow an empty array of BypassActors in Ruleset struct in CreateRuleset endpoint (#3174) Fixes: #3137. --- github/repos_rules.go | 60 ++++++++++++++++++++++++++++++++++++++ github/repos_rules_test.go | 53 +++++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+) diff --git a/github/repos_rules.go b/github/repos_rules.go index e9148f2f03b..2827f85af1c 100644 --- a/github/repos_rules.go +++ b/github/repos_rules.go @@ -408,6 +408,24 @@ type Ruleset struct { Rules []*RepositoryRule `json:"rules,omitempty"` } +// rulesetNoOmitBypassActors represents a GitHub ruleset object. The struct does not omit bypassActors if the field is nil or an empty array is passed. +type rulesetNoOmitBypassActors struct { + ID *int64 `json:"id,omitempty"` + Name string `json:"name"` + // Possible values for Target are branch, tag + Target *string `json:"target,omitempty"` + // Possible values for SourceType are: Repository, Organization + SourceType *string `json:"source_type,omitempty"` + Source string `json:"source"` + // Possible values for Enforcement are: disabled, active, evaluate + Enforcement string `json:"enforcement"` + BypassActors []*BypassActor `json:"bypass_actors"` + NodeID *string `json:"node_id,omitempty"` + Links *RulesetLinks `json:"_links,omitempty"` + Conditions *RulesetConditions `json:"conditions,omitempty"` + Rules []*RepositoryRule `json:"rules,omitempty"` +} + // GetRulesForBranch gets all the rules that apply to the specified branch. // // GitHub API docs: https://docs.github.com/rest/repos/rules#get-rules-for-a-branch @@ -520,6 +538,48 @@ func (s *RepositoriesService) UpdateRuleset(ctx context.Context, owner, repo str return ruleset, resp, nil } +// UpdateRulesetNoBypassActor updates a ruleset for the specified repository. +// +// This function is necessary as the UpdateRuleset function does not marshal ByPassActor if passed as nil or an empty array. +// +// GitHub API docs: https://docs.github.com/rest/repos/rules#update-a-repository-ruleset +// +//meta:operation PUT /repos/{owner}/{repo}/rulesets/{ruleset_id} +func (s *RepositoriesService) UpdateRulesetNoBypassActor(ctx context.Context, owner, repo string, rulesetID int64, rs *Ruleset) (*Ruleset, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/rulesets/%v", owner, repo, rulesetID) + + rsNoBypassActor := &rulesetNoOmitBypassActors{} + + if rs != nil { + rsNoBypassActor = &rulesetNoOmitBypassActors{ + ID: rs.ID, + Name: rs.Name, + Target: rs.Target, + SourceType: rs.SourceType, + Source: rs.Source, + Enforcement: rs.Enforcement, + BypassActors: rs.BypassActors, + NodeID: rs.NodeID, + Links: rs.Links, + Conditions: rs.Conditions, + Rules: rs.Rules, + } + } + + req, err := s.client.NewRequest("PUT", u, rsNoBypassActor) + if err != nil { + return nil, nil, err + } + + var ruleSet *Ruleset + resp, err := s.client.Do(ctx, req, &ruleSet) + if err != nil { + return nil, resp, err + } + + return ruleSet, resp, nil +} + // DeleteRuleset deletes a ruleset for the specified repository. // // GitHub API docs: https://docs.github.com/rest/repos/rules#delete-a-repository-ruleset diff --git a/github/repos_rules_test.go b/github/repos_rules_test.go index 23ffd3ed5c1..065d3385a3b 100644 --- a/github/repos_rules_test.go +++ b/github/repos_rules_test.go @@ -525,6 +525,58 @@ func TestRepositoriesService_GetRuleset(t *testing.T) { }) } +func TestRepositoriesService_UpdateRulesetNoBypassActor(t *testing.T) { + client, mux, _, teardown := setup() + defer teardown() + + rs := &Ruleset{ + Name: "ruleset", + Source: "o/repo", + Enforcement: "enabled", + } + + mux.HandleFunc("/repos/o/repo/rulesets/42", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "PUT") + fmt.Fprint(w, `{ + "id": 42, + "name": "ruleset", + "source_type": "Repository", + "source": "o/repo", + "enforcement": "enabled" + }`) + }) + + ctx := context.Background() + + ruleSet, _, err := client.Repositories.UpdateRulesetNoBypassActor(ctx, "o", "repo", 42, rs) + + if err != nil { + t.Errorf("Repositories.UpdateRulesetNoBypassActor returned error: %v \n", err) + } + + want := &Ruleset{ + ID: Int64(42), + Name: "ruleset", + SourceType: String("Repository"), + Source: "o/repo", + Enforcement: "enabled", + } + + if !cmp.Equal(ruleSet, want) { + t.Errorf("Repositories.UpdateRulesetNoBypassActor returned %+v, want %+v", ruleSet, want) + } + + const methodName = "UpdateRulesetNoBypassActor" + + testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { + got, resp, err := client.Repositories.UpdateRulesetNoBypassActor(ctx, "o", "repo", 42, nil) + if got != nil { + t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) + } + return resp, err + }) +} + func TestRepositoriesService_UpdateRuleset(t *testing.T) { client, mux, _, teardown := setup() defer teardown() @@ -556,6 +608,7 @@ func TestRepositoriesService_UpdateRuleset(t *testing.T) { Source: "o/repo", Enforcement: "enabled", } + if !cmp.Equal(ruleSet, want) { t.Errorf("Repositories.UpdateRuleset returned %+v, want %+v", ruleSet, want) }