Feat: Allow setting security_and_analysis settings in gh repo edit

This commit is contained in:
ChandranshuRao14 2024-12-24 12:59:42 -06:00
parent 5402e207ee
commit a542011cdc
2 changed files with 106 additions and 16 deletions

View file

@ -66,22 +66,37 @@ type EditOptions struct {
}
type EditRepositoryInput struct {
AllowForking *bool `json:"allow_forking,omitempty"`
AllowUpdateBranch *bool `json:"allow_update_branch,omitempty"`
DefaultBranch *string `json:"default_branch,omitempty"`
DeleteBranchOnMerge *bool `json:"delete_branch_on_merge,omitempty"`
Description *string `json:"description,omitempty"`
EnableAutoMerge *bool `json:"allow_auto_merge,omitempty"`
EnableIssues *bool `json:"has_issues,omitempty"`
EnableMergeCommit *bool `json:"allow_merge_commit,omitempty"`
EnableProjects *bool `json:"has_projects,omitempty"`
EnableDiscussions *bool `json:"has_discussions,omitempty"`
EnableRebaseMerge *bool `json:"allow_rebase_merge,omitempty"`
EnableSquashMerge *bool `json:"allow_squash_merge,omitempty"`
EnableWiki *bool `json:"has_wiki,omitempty"`
Homepage *string `json:"homepage,omitempty"`
IsTemplate *bool `json:"is_template,omitempty"`
Visibility *string `json:"visibility,omitempty"`
enableAdvancedSecurity *bool
enableSecretScanning *bool
enableSecretScanningPushProtection *bool
AllowForking *bool `json:"allow_forking,omitempty"`
AllowUpdateBranch *bool `json:"allow_update_branch,omitempty"`
DefaultBranch *string `json:"default_branch,omitempty"`
DeleteBranchOnMerge *bool `json:"delete_branch_on_merge,omitempty"`
Description *string `json:"description,omitempty"`
EnableAutoMerge *bool `json:"allow_auto_merge,omitempty"`
EnableIssues *bool `json:"has_issues,omitempty"`
EnableMergeCommit *bool `json:"allow_merge_commit,omitempty"`
EnableProjects *bool `json:"has_projects,omitempty"`
EnableDiscussions *bool `json:"has_discussions,omitempty"`
EnableRebaseMerge *bool `json:"allow_rebase_merge,omitempty"`
EnableSquashMerge *bool `json:"allow_squash_merge,omitempty"`
EnableWiki *bool `json:"has_wiki,omitempty"`
Homepage *string `json:"homepage,omitempty"`
IsTemplate *bool `json:"is_template,omitempty"`
SecurityAndAnalysis *SecurityAndAnalysisInput `json:"security_and_analysis,omitempty"`
Visibility *string `json:"visibility,omitempty"`
}
type SecurityAndAnalysisInput struct {
EnableAdvancedSecurity *SecurityAndAnalysisStatus `json:"advanced_security,omitempty"`
EnableSecretScanning *SecurityAndAnalysisStatus `json:"secret_scanning,omitempty"`
EnableSecretScanningPushProtection *SecurityAndAnalysisStatus `json:"secret_scanning_push_protection,omitempty"`
}
type SecurityAndAnalysisStatus struct {
Status *string `json:"status,omitempty"`
}
func NewCmdEdit(f *cmdutil.Factory, runF func(options *EditOptions) error) *cobra.Command {
@ -177,6 +192,9 @@ func NewCmdEdit(f *cmdutil.Factory, runF func(options *EditOptions) error) *cobr
cmdutil.NilBoolFlag(cmd, &opts.Edits.EnableSquashMerge, "enable-squash-merge", "", "Enable merging pull requests via squashed commit")
cmdutil.NilBoolFlag(cmd, &opts.Edits.EnableRebaseMerge, "enable-rebase-merge", "", "Enable merging pull requests via rebase")
cmdutil.NilBoolFlag(cmd, &opts.Edits.EnableAutoMerge, "enable-auto-merge", "", "Enable auto-merge functionality")
cmdutil.NilBoolFlag(cmd, &opts.Edits.enableAdvancedSecurity, "enable-advanced-security", "", "Enable advanced security in the repository")
cmdutil.NilBoolFlag(cmd, &opts.Edits.enableSecretScanning, "enable-secret-scanning", "", "Enable secret scanning in the repository")
cmdutil.NilBoolFlag(cmd, &opts.Edits.enableSecretScanningPushProtection, "enable-secret-scanning-push-protection", "", "Enable secret scanning push protection in the repository. Secret scanning must be enabled first")
cmdutil.NilBoolFlag(cmd, &opts.Edits.DeleteBranchOnMerge, "delete-branch-on-merge", "", "Delete head branch when pull requests are merged")
cmdutil.NilBoolFlag(cmd, &opts.Edits.AllowForking, "allow-forking", "", "Allow forking of an organization repository")
cmdutil.NilBoolFlag(cmd, &opts.Edits.AllowUpdateBranch, "allow-update-branch", "", "Allow a pull request head branch that is behind its base branch to be updated")
@ -240,6 +258,34 @@ func editRun(ctx context.Context, opts *EditOptions) error {
}
}
if hasSecurityEdits(opts.Edits) {
apiClient := api.NewClientFromHTTP(opts.HTTPClient)
repo, err := api.FetchRepository(apiClient, opts.Repository, []string{"viewerCanAdminister"})
if err != nil {
return err
}
if !repo.ViewerCanAdminister {
return fmt.Errorf("you do not have sufficient permissions to edit repository security and analysis features")
}
opts.Edits.SecurityAndAnalysis = &SecurityAndAnalysisInput{}
if opts.Edits.enableAdvancedSecurity != nil {
opts.Edits.SecurityAndAnalysis.EnableAdvancedSecurity = &SecurityAndAnalysisStatus{
Status: boolToStatus(*opts.Edits.enableAdvancedSecurity),
}
}
if opts.Edits.enableSecretScanning != nil {
opts.Edits.SecurityAndAnalysis.EnableSecretScanning = &SecurityAndAnalysisStatus{
Status: boolToStatus(*opts.Edits.enableSecretScanning),
}
}
if opts.Edits.enableSecretScanningPushProtection != nil {
opts.Edits.SecurityAndAnalysis.EnableSecretScanningPushProtection = &SecurityAndAnalysisStatus{
Status: boolToStatus(*opts.Edits.enableSecretScanningPushProtection),
}
}
}
apiPath := fmt.Sprintf("repos/%s/%s", repo.RepoOwner(), repo.RepoName())
body := &bytes.Buffer{}
@ -560,3 +606,17 @@ func isIncluded(value string, opts []string) bool {
}
return false
}
func boolToStatus(status bool) *string {
var result string
if status {
result = "enabled"
} else {
result = "disabled"
}
return &result
}
func hasSecurityEdits(edits EditRepositoryInput) bool {
return edits.enableAdvancedSecurity != nil || edits.enableSecretScanning != nil || edits.enableSecretScanningPushProtection != nil
}

View file

@ -201,6 +201,36 @@ func Test_editRun(t *testing.T) {
}))
},
},
{
name: "enable/disable security and analysis settings",
opts: EditOptions{
Repository: ghrepo.NewWithHost("OWNER", "REPO", "github.com"),
Edits: EditRepositoryInput{
SecurityAndAnalysis: &SecurityAndAnalysisInput{
EnableAdvancedSecurity: &SecurityAndAnalysisStatus{
Status: sp("enabled"),
},
EnableSecretScanning: &SecurityAndAnalysisStatus{
Status: sp("enabled"),
},
EnableSecretScanningPushProtection: &SecurityAndAnalysisStatus{
Status: sp("disabled"),
},
},
},
},
httpStubs: func(t *testing.T, r *httpmock.Registry) {
r.Register(
httpmock.REST("PATCH", "repos/OWNER/REPO"),
httpmock.RESTPayload(200, `{}`, func(payload map[string]interface{}) {
assert.Equal(t, 1, len(payload))
securityAndAnalysis := payload["security_and_analysis"].(map[string]interface{})
assert.Equal(t, "enabled", securityAndAnalysis["advanced_security"].(map[string]interface{})["status"])
assert.Equal(t, "enabled", securityAndAnalysis["secret_scanning"].(map[string]interface{})["status"])
assert.Equal(t, "disabled", securityAndAnalysis["secret_scanning_push_protection"].(map[string]interface{})["status"])
}))
},
},
}
for _, tt := range tests {