@@ -7,17 +7,18 @@ package github
77
88import (
99 "encoding/json"
10- "reflect "
10+ "fmt "
1111)
1212
1313// RulesetTarget represents a GitHub ruleset target.
1414type RulesetTarget string
1515
1616// This is the set of GitHub ruleset targets.
1717const (
18- RulesetTargetBranch RulesetTarget = "branch"
19- RulesetTargetTag RulesetTarget = "tag"
20- RulesetTargetPush RulesetTarget = "push"
18+ RulesetTargetBranch RulesetTarget = "branch"
19+ RulesetTargetTag RulesetTarget = "tag"
20+ RulesetTargetPush RulesetTarget = "push"
21+ RulesetTargetRepository RulesetTarget = "repository"
2122)
2223
2324// RulesetSourceType represents a GitHub ruleset source type.
@@ -68,27 +69,37 @@ type RepositoryRuleType string
6869
6970// This is the set of GitHub ruleset rule types.
7071const (
72+ // Branch or tag target rules.
73+ RulesetRuleTypeBranchNamePattern RepositoryRuleType = "branch_name_pattern"
74+ RulesetRuleTypeCodeScanning RepositoryRuleType = "code_scanning"
75+ RulesetRuleTypeCommitAuthorEmailPattern RepositoryRuleType = "commit_author_email_pattern"
76+ RulesetRuleTypeCommitMessagePattern RepositoryRuleType = "commit_message_pattern"
77+ RulesetRuleTypeCommitterEmailPattern RepositoryRuleType = "committer_email_pattern"
7178 RulesetRuleTypeCreation RepositoryRuleType = "creation"
72- RulesetRuleTypeUpdate RepositoryRuleType = "update"
7379 RulesetRuleTypeDeletion RepositoryRuleType = "deletion"
74- RulesetRuleTypeRequiredLinearHistory RepositoryRuleType = "required_linear_history"
7580 RulesetRuleTypeMergeQueue RepositoryRuleType = "merge_queue"
81+ RulesetRuleTypeNonFastForward RepositoryRuleType = "non_fast_forward"
82+ RulesetRuleTypePullRequest RepositoryRuleType = "pull_request"
7683 RulesetRuleTypeRequiredDeployments RepositoryRuleType = "required_deployments"
84+ RulesetRuleTypeRequiredLinearHistory RepositoryRuleType = "required_linear_history"
7785 RulesetRuleTypeRequiredSignatures RepositoryRuleType = "required_signatures"
78- RulesetRuleTypePullRequest RepositoryRuleType = "pull_request"
7986 RulesetRuleTypeRequiredStatusChecks RepositoryRuleType = "required_status_checks"
80- RulesetRuleTypeNonFastForward RepositoryRuleType = "non_fast_forward"
81- RulesetRuleTypeCommitMessagePattern RepositoryRuleType = "commit_message_pattern"
82- RulesetRuleTypeCommitAuthorEmailPattern RepositoryRuleType = "commit_author_email_pattern"
83- RulesetRuleTypeCommitterEmailPattern RepositoryRuleType = "committer_email_pattern"
84- RulesetRuleTypeBranchNamePattern RepositoryRuleType = "branch_name_pattern"
8587 RulesetRuleTypeTagNamePattern RepositoryRuleType = "tag_name_pattern"
88+ RulesetRuleTypeUpdate RepositoryRuleType = "update"
89+ RulesetRuleTypeWorkflows RepositoryRuleType = "workflows"
90+
91+ // Push target rules.
92+ RulesetRuleTypeFileExtensionRestriction RepositoryRuleType = "file_extension_restriction"
8693 RulesetRuleTypeFilePathRestriction RepositoryRuleType = "file_path_restriction"
8794 RulesetRuleTypeMaxFilePathLength RepositoryRuleType = "max_file_path_length"
88- RulesetRuleTypeFileExtensionRestriction RepositoryRuleType = "file_extension_restriction"
8995 RulesetRuleTypeMaxFileSize RepositoryRuleType = "max_file_size"
90- RulesetRuleTypeWorkflows RepositoryRuleType = "workflows"
91- RulesetRuleTypeCodeScanning RepositoryRuleType = "code_scanning"
96+
97+ // Repository target rules.
98+ RulesetRuleTypeRepositoryCreate RepositoryRuleType = "repository_create"
99+ RulesetRuleTypeRepositoryDelete RepositoryRuleType = "repository_delete"
100+ RulesetRuleTypeRepositoryName RepositoryRuleType = "repository_name"
101+ RulesetRuleTypeRepositoryTransfer RepositoryRuleType = "repository_transfer"
102+ RulesetRuleTypeRepositoryVisibility RepositoryRuleType = "repository_visibility"
92103)
93104
94105// MergeGroupingStrategy models a GitHub merge grouping strategy.
@@ -277,6 +288,7 @@ type RepositoryRule struct {
277288// RepositoryRulesetRules represents a GitHub ruleset rules object.
278289// This type doesn't have JSON annotations as it uses custom marshaling.
279290type RepositoryRulesetRules struct {
291+ // Branch or tag target rules.
280292 Creation * EmptyRuleParameters
281293 Update * UpdateRuleParameters
282294 Deletion * EmptyRuleParameters
@@ -292,17 +304,27 @@ type RepositoryRulesetRules struct {
292304 CommitterEmailPattern * PatternRuleParameters
293305 BranchNamePattern * PatternRuleParameters
294306 TagNamePattern * PatternRuleParameters
307+ Workflows * WorkflowsRuleParameters
308+ CodeScanning * CodeScanningRuleParameters
309+
310+ // Push target rules.
311+ FileExtensionRestriction * FileExtensionRestrictionRuleParameters
295312 FilePathRestriction * FilePathRestrictionRuleParameters
296313 MaxFilePathLength * MaxFilePathLengthRuleParameters
297- FileExtensionRestriction * FileExtensionRestrictionRuleParameters
298314 MaxFileSize * MaxFileSizeRuleParameters
299- Workflows * WorkflowsRuleParameters
300- CodeScanning * CodeScanningRuleParameters
315+
316+ // Repository target rules.
317+ RepositoryCreate * EmptyRuleParameters
318+ RepositoryDelete * EmptyRuleParameters
319+ RepositoryName * SimplePatternRuleParameters
320+ RepositoryTransfer * EmptyRuleParameters
321+ RepositoryVisibility * RepositoryVisibilityRuleParameters
301322}
302323
303324// BranchRules represents the rules active for a GitHub repository branch.
304325// This type doesn't have JSON annotations as it uses custom marshaling.
305326type BranchRules struct {
327+ // Branch or tag target rules.
306328 Creation []* BranchRuleMetadata
307329 Update []* UpdateBranchRule
308330 Deletion []* BranchRuleMetadata
@@ -318,12 +340,14 @@ type BranchRules struct {
318340 CommitterEmailPattern []* PatternBranchRule
319341 BranchNamePattern []* PatternBranchRule
320342 TagNamePattern []* PatternBranchRule
343+ Workflows []* WorkflowsBranchRule
344+ CodeScanning []* CodeScanningBranchRule
345+
346+ // Push target rules.
347+ FileExtensionRestriction []* FileExtensionRestrictionBranchRule
321348 FilePathRestriction []* FilePathRestrictionBranchRule
322349 MaxFilePathLength []* MaxFilePathLengthBranchRule
323- FileExtensionRestriction []* FileExtensionRestrictionBranchRule
324350 MaxFileSize []* MaxFileSizeBranchRule
325- Workflows []* WorkflowsBranchRule
326- CodeScanning []* CodeScanningBranchRule
327351}
328352
329353// BranchRuleMetadata represents the metadata for a branch rule.
@@ -522,6 +546,18 @@ type RuleCodeScanningTool struct {
522546 Tool string `json:"tool"`
523547}
524548
549+ // SimplePatternRuleParameters represents the parameters for a simple pattern rule.
550+ type SimplePatternRuleParameters struct {
551+ Negate bool `json:"negate"`
552+ Pattern string `json:"pattern"`
553+ }
554+
555+ // RepositoryVisibilityRuleParameters represents the repository visibility rule parameters.
556+ type RepositoryVisibilityRuleParameters struct {
557+ Internal bool `json:"internal"`
558+ Private bool `json:"private"`
559+ }
560+
525561// repositoryRulesetRuleWrapper is a helper type to marshal & unmarshal a ruleset rule.
526562type repositoryRulesetRuleWrapper struct {
527563 Type RepositoryRuleType `json:"type"`
@@ -702,17 +738,74 @@ func (r *RepositoryRulesetRules) MarshalJSON() ([]byte, error) {
702738 rawRules = append (rawRules , json .RawMessage (bytes ))
703739 }
704740
741+ if r .RepositoryCreate != nil {
742+ bytes , err := marshalRepositoryRulesetRule (RulesetRuleTypeRepositoryCreate , r .RepositoryCreate )
743+ if err != nil {
744+ return nil , err
745+ }
746+ rawRules = append (rawRules , json .RawMessage (bytes ))
747+ }
748+
749+ if r .RepositoryDelete != nil {
750+ bytes , err := marshalRepositoryRulesetRule (RulesetRuleTypeRepositoryDelete , r .RepositoryDelete )
751+ if err != nil {
752+ return nil , err
753+ }
754+ rawRules = append (rawRules , json .RawMessage (bytes ))
755+ }
756+
757+ if r .RepositoryName != nil {
758+ bytes , err := marshalRepositoryRulesetRule (RulesetRuleTypeRepositoryName , r .RepositoryName )
759+ if err != nil {
760+ return nil , err
761+ }
762+ rawRules = append (rawRules , json .RawMessage (bytes ))
763+ }
764+
765+ if r .RepositoryTransfer != nil {
766+ bytes , err := marshalRepositoryRulesetRule (RulesetRuleTypeRepositoryTransfer , r .RepositoryTransfer )
767+ if err != nil {
768+ return nil , err
769+ }
770+ rawRules = append (rawRules , json .RawMessage (bytes ))
771+ }
772+
773+ if r .RepositoryVisibility != nil {
774+ bytes , err := marshalRepositoryRulesetRule (RulesetRuleTypeRepositoryVisibility , r .RepositoryVisibility )
775+ if err != nil {
776+ return nil , err
777+ }
778+ rawRules = append (rawRules , json .RawMessage (bytes ))
779+ }
780+
705781 return json .Marshal (rawRules )
706782}
707783
708784// marshalRepositoryRulesetRule is a helper function to marshal a ruleset rule.
709- //
710- // TODO: Benchmark the code that uses reflection.
711- // TODO: Use a generator here instead of reflection if there is a significant performance hit.
712785func marshalRepositoryRulesetRule [T any ](t RepositoryRuleType , params T ) ([]byte , error ) {
713- paramsType := reflect .TypeFor [T ]()
786+ hasParams := true
787+
788+ switch t {
789+ case RulesetRuleTypeCreation ,
790+ RulesetRuleTypeDeletion ,
791+ RulesetRuleTypeRequiredLinearHistory ,
792+ RulesetRuleTypeRequiredSignatures ,
793+ RulesetRuleTypeNonFastForward ,
794+ RulesetRuleTypeRepositoryCreate ,
795+ RulesetRuleTypeRepositoryDelete ,
796+ RulesetRuleTypeRepositoryTransfer :
797+ hasParams = false
798+ case RulesetRuleTypeUpdate :
799+ paramsTyped , ok := any (params ).(* UpdateRuleParameters )
800+ if ! ok {
801+ return nil , fmt .Errorf ("expected UpdateRuleParameters for rule type %v" , t )
802+ }
803+ if paramsTyped == nil || * paramsTyped == (UpdateRuleParameters {}) {
804+ hasParams = false
805+ }
806+ }
714807
715- if paramsType . Kind () == reflect . Pointer && ( reflect . ValueOf ( params ). IsNil () || reflect . ValueOf ( params ). Elem (). IsZero ()) {
808+ if ! hasParams {
716809 return json .Marshal (repositoryRulesetRuleWrapper {Type : t })
717810 }
718811
@@ -872,6 +965,28 @@ func (r *RepositoryRulesetRules) UnmarshalJSON(data []byte) error {
872965 return err
873966 }
874967 }
968+ case RulesetRuleTypeRepositoryCreate :
969+ r .RepositoryCreate = & EmptyRuleParameters {}
970+ case RulesetRuleTypeRepositoryDelete :
971+ r .RepositoryDelete = & EmptyRuleParameters {}
972+ case RulesetRuleTypeRepositoryName :
973+ r .RepositoryName = & SimplePatternRuleParameters {}
974+
975+ if w .Parameters != nil {
976+ if err := json .Unmarshal (w .Parameters , r .RepositoryName ); err != nil {
977+ return err
978+ }
979+ }
980+ case RulesetRuleTypeRepositoryTransfer :
981+ r .RepositoryTransfer = & EmptyRuleParameters {}
982+ case RulesetRuleTypeRepositoryVisibility :
983+ r .RepositoryVisibility = & RepositoryVisibilityRuleParameters {}
984+
985+ if w .Parameters != nil {
986+ if err := json .Unmarshal (w .Parameters , r .RepositoryVisibility ); err != nil {
987+ return err
988+ }
989+ }
875990 }
876991 }
877992
@@ -1251,6 +1366,31 @@ func (r *RepositoryRule) UnmarshalJSON(data []byte) error {
12511366 }
12521367 }
12531368
1369+ r .Parameters = p
1370+ case RulesetRuleTypeRepositoryCreate :
1371+ r .Parameters = nil
1372+ case RulesetRuleTypeRepositoryDelete :
1373+ r .Parameters = nil
1374+ case RulesetRuleTypeRepositoryName :
1375+ p := & SimplePatternRuleParameters {}
1376+
1377+ if w .Parameters != nil {
1378+ if err := json .Unmarshal (w .Parameters , p ); err != nil {
1379+ return err
1380+ }
1381+ }
1382+
1383+ r .Parameters = p
1384+ case RulesetRuleTypeRepositoryTransfer :
1385+ r .Parameters = nil
1386+ case RulesetRuleTypeRepositoryVisibility :
1387+ p := & RepositoryVisibilityRuleParameters {}
1388+
1389+ if w .Parameters != nil {
1390+ if err := json .Unmarshal (w .Parameters , p ); err != nil {
1391+ return err
1392+ }
1393+ }
12541394 r .Parameters = p
12551395 }
12561396
0 commit comments