From faa61be3a156a475bab8f10b7681194b0c6f63f7 Mon Sep 17 00:00:00 2001 From: Aditya Mahendrakar Date: Wed, 23 Oct 2024 12:20:04 -0700 Subject: [PATCH 1/3] add event structs for branch_protection_configuration and secret_scanning_alert_location --- github/event_types.go | 27 ++++++++ github/github-accessors.go | 104 ++++++++++++++++++++++++++++++ github/github-accessors_test.go | 110 ++++++++++++++++++++++++++++++++ 3 files changed, 241 insertions(+) diff --git a/github/event_types.go b/github/event_types.go index f9778215092..40ad919be5e 100644 --- a/github/event_types.go +++ b/github/event_types.go @@ -29,6 +29,19 @@ type BranchProtectionRuleEvent struct { Installation *Installation `json:"installation,omitempty"` } +// BranchProtectionConfigurationEvent is triggered when there is a change to branch protection configurations for a repository. +// The Webhook event name is "branch_protection_configuration". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#branch_protection_configuration +type BranchProtectionConfigurationEvent struct { + Action *string `json:"action,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Org *Organization `json:"organization,omitempty"` + Enterprise *Enterprise `json:"enterprise,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + // CheckRunEvent is triggered when a check run is "created", "completed", or "rerequested". // The Webhook event name is "check_run". // @@ -1580,6 +1593,20 @@ type SecretScanningAlertEvent struct { Installation *Installation `json:"installation,omitempty"` } +// SecretScanningAlertLocationEvent is triggered when there is activity relating to the locations of a secret in a secret scanning alert. +// The Webhook event name is "secret_scanning_alert_location". +// +// GitHub API docs: https://docs.github.com/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#secret_scanning_alert_location +type SecretScanningAlertLocationEvent struct { + Action *string `json:"action,omitempty"` + Alert *SecretScanningAlert `json:"alert,omitempty"` + Installation *Installation `json:"installation,omitempty"` + Location *SecretScanningAlertLocation `json:"location,omitempty"` + Organization *Organization `json:"organization,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` +} + // SecurityAndAnalysisEvent is triggered when code security and analysis features // are enabled or disabled for a repository. // diff --git a/github/github-accessors.go b/github/github-accessors.go index ea4cfb75da1..9341e001d49 100644 --- a/github/github-accessors.go +++ b/github/github-accessors.go @@ -1646,6 +1646,54 @@ func (b *BranchPolicy) GetProtectedBranches() bool { return *b.ProtectedBranches } +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (b *BranchProtectionConfigurationEvent) GetAction() string { + if b == nil || b.Action == nil { + return "" + } + return *b.Action +} + +// GetEnterprise returns the Enterprise field. +func (b *BranchProtectionConfigurationEvent) GetEnterprise() *Enterprise { + if b == nil { + return nil + } + return b.Enterprise +} + +// GetInstallation returns the Installation field. +func (b *BranchProtectionConfigurationEvent) GetInstallation() *Installation { + if b == nil { + return nil + } + return b.Installation +} + +// GetOrg returns the Org field. +func (b *BranchProtectionConfigurationEvent) GetOrg() *Organization { + if b == nil { + return nil + } + return b.Org +} + +// GetRepo returns the Repo field. +func (b *BranchProtectionConfigurationEvent) GetRepo() *Repository { + if b == nil { + return nil + } + return b.Repo +} + +// GetSender returns the Sender field. +func (b *BranchProtectionConfigurationEvent) GetSender() *User { + if b == nil { + return nil + } + return b.Sender +} + // GetAdminEnforced returns the AdminEnforced field if it's non-nil, zero value otherwise. func (b *BranchProtectionRule) GetAdminEnforced() bool { if b == nil || b.AdminEnforced == nil { @@ -22918,6 +22966,62 @@ func (s *SecretScanningAlertLocationDetails) GetStartline() int { return *s.Startline } +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlertLocationEvent) GetAction() string { + if s == nil || s.Action == nil { + return "" + } + return *s.Action +} + +// GetAlert returns the Alert field. +func (s *SecretScanningAlertLocationEvent) GetAlert() *SecretScanningAlert { + if s == nil { + return nil + } + return s.Alert +} + +// GetInstallation returns the Installation field. +func (s *SecretScanningAlertLocationEvent) GetInstallation() *Installation { + if s == nil { + return nil + } + return s.Installation +} + +// GetLocation returns the Location field. +func (s *SecretScanningAlertLocationEvent) GetLocation() *SecretScanningAlertLocation { + if s == nil { + return nil + } + return s.Location +} + +// GetOrganization returns the Organization field. +func (s *SecretScanningAlertLocationEvent) GetOrganization() *Organization { + if s == nil { + return nil + } + return s.Organization +} + +// GetRepo returns the Repo field. +func (s *SecretScanningAlertLocationEvent) GetRepo() *Repository { + if s == nil { + return nil + } + return s.Repo +} + +// GetSender returns the Sender field. +func (s *SecretScanningAlertLocationEvent) GetSender() *User { + if s == nil { + return nil + } + return s.Sender +} + // GetResolution returns the Resolution field if it's non-nil, zero value otherwise. func (s *SecretScanningAlertUpdateOptions) GetResolution() string { if s == nil || s.Resolution == nil { diff --git a/github/github-accessors_test.go b/github/github-accessors_test.go index acd3febe8f6..90966654517 100644 --- a/github/github-accessors_test.go +++ b/github/github-accessors_test.go @@ -2163,6 +2163,57 @@ func TestBranchPolicy_GetProtectedBranches(tt *testing.T) { b.GetProtectedBranches() } +func TestBranchProtectionConfigurationEvent_GetAction(tt *testing.T) { + tt.Parallel() + var zeroValue string + b := &BranchProtectionConfigurationEvent{Action: &zeroValue} + b.GetAction() + b = &BranchProtectionConfigurationEvent{} + b.GetAction() + b = nil + b.GetAction() +} + +func TestBranchProtectionConfigurationEvent_GetEnterprise(tt *testing.T) { + tt.Parallel() + b := &BranchProtectionConfigurationEvent{} + b.GetEnterprise() + b = nil + b.GetEnterprise() +} + +func TestBranchProtectionConfigurationEvent_GetInstallation(tt *testing.T) { + tt.Parallel() + b := &BranchProtectionConfigurationEvent{} + b.GetInstallation() + b = nil + b.GetInstallation() +} + +func TestBranchProtectionConfigurationEvent_GetOrg(tt *testing.T) { + tt.Parallel() + b := &BranchProtectionConfigurationEvent{} + b.GetOrg() + b = nil + b.GetOrg() +} + +func TestBranchProtectionConfigurationEvent_GetRepo(tt *testing.T) { + tt.Parallel() + b := &BranchProtectionConfigurationEvent{} + b.GetRepo() + b = nil + b.GetRepo() +} + +func TestBranchProtectionConfigurationEvent_GetSender(tt *testing.T) { + tt.Parallel() + b := &BranchProtectionConfigurationEvent{} + b.GetSender() + b = nil + b.GetSender() +} + func TestBranchProtectionRule_GetAdminEnforced(tt *testing.T) { tt.Parallel() var zeroValue bool @@ -29393,6 +29444,65 @@ func TestSecretScanningAlertLocationDetails_GetStartline(tt *testing.T) { s.GetStartline() } +func TestSecretScanningAlertLocationEvent_GetAction(tt *testing.T) { + tt.Parallel() + var zeroValue string + s := &SecretScanningAlertLocationEvent{Action: &zeroValue} + s.GetAction() + s = &SecretScanningAlertLocationEvent{} + s.GetAction() + s = nil + s.GetAction() +} + +func TestSecretScanningAlertLocationEvent_GetAlert(tt *testing.T) { + tt.Parallel() + s := &SecretScanningAlertLocationEvent{} + s.GetAlert() + s = nil + s.GetAlert() +} + +func TestSecretScanningAlertLocationEvent_GetInstallation(tt *testing.T) { + tt.Parallel() + s := &SecretScanningAlertLocationEvent{} + s.GetInstallation() + s = nil + s.GetInstallation() +} + +func TestSecretScanningAlertLocationEvent_GetLocation(tt *testing.T) { + tt.Parallel() + s := &SecretScanningAlertLocationEvent{} + s.GetLocation() + s = nil + s.GetLocation() +} + +func TestSecretScanningAlertLocationEvent_GetOrganization(tt *testing.T) { + tt.Parallel() + s := &SecretScanningAlertLocationEvent{} + s.GetOrganization() + s = nil + s.GetOrganization() +} + +func TestSecretScanningAlertLocationEvent_GetRepo(tt *testing.T) { + tt.Parallel() + s := &SecretScanningAlertLocationEvent{} + s.GetRepo() + s = nil + s.GetRepo() +} + +func TestSecretScanningAlertLocationEvent_GetSender(tt *testing.T) { + tt.Parallel() + s := &SecretScanningAlertLocationEvent{} + s.GetSender() + s = nil + s.GetSender() +} + func TestSecretScanningAlertUpdateOptions_GetResolution(tt *testing.T) { tt.Parallel() var zeroValue string From 281757562987b6aa378f1ca7094aaaa350efbeb2 Mon Sep 17 00:00:00 2001 From: Aditya Mahendrakar Date: Wed, 23 Oct 2024 16:11:15 -0700 Subject: [PATCH 2/3] update messages.go and add tests for the event structs --- github/event_types_test.go | 147 +++++++++++++++++++++++++++++++++++++ github/messages.go | 138 +++++++++++++++++----------------- github/messages_test.go | 8 ++ 3 files changed, 225 insertions(+), 68 deletions(-) diff --git a/github/event_types_test.go b/github/event_types_test.go index 0c4deab4177..3883c9f0acb 100644 --- a/github/event_types_test.go +++ b/github/event_types_test.go @@ -265,6 +265,61 @@ func TestProjectColumnChange_Marshal_NameChange(t *testing.T) { testJSONMarshal(t, u, want) } +func TestBranchProtectionConfigurationEvent_Marshal(t *testing.T) { + t.Parallel() + testJSONMarshal(t, &BranchProtectionConfigurationEvent{}, "{}") + u := &BranchProtectionConfigurationEvent{ + Action: String("enabled"), + Repo: &Repository{ + ID: Int64(12345), + NodeID: String("MDEwOlJlcG9zaXRvcnkxMjM0NQ=="), + Name: String("example-repo"), + }, + Org: &Organization{ + Login: String("example-org"), + ID: Int64(67890), + }, + Sender: &User{ + Login: String("example-user"), + ID: Int64(1111), + }, + Installation: &Installation{ + ID: Int64(2222), + }, + Enterprise: &Enterprise{ + ID: Int(3333), + Slug: String("example-enterprise"), + Name: String("Example Enterprise"), + }, + } + + want := `{ + "action": "enabled", + "repository": { + "id": 12345, + "node_id": "MDEwOlJlcG9zaXRvcnkxMjM0NQ==", + "name": "example-repo" + }, + "organization": { + "login": "example-org", + "id": 67890 + }, + "sender": { + "login": "example-user", + "id": 1111 + }, + "installation": { + "id": 2222 + }, + "enterprise": { + "id": 3333, + "slug": "example-enterprise", + "name": "Example Enterprise" + } + }` + testJSONMarshal(t, u, want) +} + func TestTeamAddEvent_Marshal(t *testing.T) { t.Parallel() testJSONMarshal(t, &TeamAddEvent{}, "{}") @@ -19295,6 +19350,98 @@ func TestSecretScanningAlertEvent_Marshal(t *testing.T) { testJSONMarshal(t, u, want) } +func TestSecretScanningAlertLocationEvent_Marshal(t *testing.T) { + t.Parallel() + testJSONMarshal(t, &SecretScanningAlertLocationEvent{}, "{}") + u := &SecretScanningAlertLocationEvent{ + Action: String("created"), + Alert: &SecretScanningAlert{ + Number: Int(10), + CreatedAt: &Timestamp{referenceTime}, + UpdatedAt: &Timestamp{referenceTime}, + URL: String("a"), + HTMLURL: String("a"), + SecretType: String("mailchimp_api_key"), + }, + Location: &SecretScanningAlertLocation{ + Type: String("blob"), + Details: &SecretScanningAlertLocationDetails{ + Path: String("path/to/file"), + Startline: Int(10), + EndLine: Int(20), + StartColumn: Int(1), + EndColumn: Int(2), + BlobSHA: String("d6e4c75c141dbacecc279b721b8bsomeSHA"), + BlobURL: String("a"), + CommitSHA: String("d6e4c75c141dbacecc279b721b8bsomeSHA"), + CommitURL: String("a"), + }, + }, + Repo: &Repository{ + ID: Int64(12345), + NodeID: String("MDEwOlJlcG9zaXRvcnkxMjM0NQ=="), + Name: String("example-repo"), + }, + Organization: &Organization{ + Login: String("example-org"), + ID: Int64(67890), + }, + Sender: &User{ + Login: String("example-user"), + ID: Int64(1111), + }, + Installation: &Installation{ + ID: Int64(2222), + }, + } + + want := `{ + "action": "created", + "alert": { + "number": 10, + "created_at": ` + referenceTimeStr + `, + "updated_at": ` + referenceTimeStr + `, + "url": "a", + "html_url": "a", + "secret_type": "mailchimp_api_key" + }, + "location": { + + "type": "blob", + "details": { + "path": "path/to/file", + "start_line": 10, + "end_line": 20, + "start_column": 1, + "end_column": 2, + "blob_sha": "d6e4c75c141dbacecc279b721b8bsomeSHA", + "blob_url": "a", + "commit_sha": "d6e4c75c141dbacecc279b721b8bsomeSHA", + "commit_url": "a" + } + }, + "repository": { + + "id": 12345, + "node_id": "MDEwOlJlcG9zaXRvcnkxMjM0NQ==", + "name": "example-repo" + }, + "organization": { + "login": "example-org", + "id": 67890 + }, + "sender": { + "login": "example-user", + "id": 1111 + }, + "installation": { + "id": 2222 + } + }` + + testJSONMarshal(t, u, want) +} + func TestSecurityAdvisoryEvent_Marshal(t *testing.T) { t.Parallel() testJSONMarshal(t, &SecurityAdvisoryEvent{}, "{}") diff --git a/github/messages.go b/github/messages.go index f365190ae39..608c557cb09 100644 --- a/github/messages.go +++ b/github/messages.go @@ -46,74 +46,76 @@ const ( var ( // eventTypeMapping maps webhooks types to their corresponding go-github struct types. eventTypeMapping = map[string]interface{}{ - "branch_protection_rule": &BranchProtectionRuleEvent{}, - "check_run": &CheckRunEvent{}, - "check_suite": &CheckSuiteEvent{}, - "code_scanning_alert": &CodeScanningAlertEvent{}, - "commit_comment": &CommitCommentEvent{}, - "content_reference": &ContentReferenceEvent{}, - "create": &CreateEvent{}, - "delete": &DeleteEvent{}, - "dependabot_alert": &DependabotAlertEvent{}, - "deploy_key": &DeployKeyEvent{}, - "deployment": &DeploymentEvent{}, - "deployment_review": &DeploymentReviewEvent{}, - "deployment_status": &DeploymentStatusEvent{}, - "deployment_protection_rule": &DeploymentProtectionRuleEvent{}, - "discussion": &DiscussionEvent{}, - "discussion_comment": &DiscussionCommentEvent{}, - "fork": &ForkEvent{}, - "github_app_authorization": &GitHubAppAuthorizationEvent{}, - "gollum": &GollumEvent{}, - "installation": &InstallationEvent{}, - "installation_repositories": &InstallationRepositoriesEvent{}, - "installation_target": &InstallationTargetEvent{}, - "issue_comment": &IssueCommentEvent{}, - "issues": &IssuesEvent{}, - "label": &LabelEvent{}, - "marketplace_purchase": &MarketplacePurchaseEvent{}, - "member": &MemberEvent{}, - "membership": &MembershipEvent{}, - "merge_group": &MergeGroupEvent{}, - "meta": &MetaEvent{}, - "milestone": &MilestoneEvent{}, - "organization": &OrganizationEvent{}, - "org_block": &OrgBlockEvent{}, - "package": &PackageEvent{}, - "page_build": &PageBuildEvent{}, - "personal_access_token_request": &PersonalAccessTokenRequestEvent{}, - "ping": &PingEvent{}, - "project": &ProjectEvent{}, - "project_card": &ProjectCardEvent{}, - "project_column": &ProjectColumnEvent{}, - "projects_v2": &ProjectV2Event{}, - "projects_v2_item": &ProjectV2ItemEvent{}, - "public": &PublicEvent{}, - "pull_request": &PullRequestEvent{}, - "pull_request_review": &PullRequestReviewEvent{}, - "pull_request_review_comment": &PullRequestReviewCommentEvent{}, - "pull_request_review_thread": &PullRequestReviewThreadEvent{}, - "pull_request_target": &PullRequestTargetEvent{}, - "push": &PushEvent{}, - "repository": &RepositoryEvent{}, - "repository_dispatch": &RepositoryDispatchEvent{}, - "repository_import": &RepositoryImportEvent{}, - "repository_ruleset": &RepositoryRulesetEvent{}, - "repository_vulnerability_alert": &RepositoryVulnerabilityAlertEvent{}, - "release": &ReleaseEvent{}, - "secret_scanning_alert": &SecretScanningAlertEvent{}, - "security_advisory": &SecurityAdvisoryEvent{}, - "security_and_analysis": &SecurityAndAnalysisEvent{}, - "sponsorship": &SponsorshipEvent{}, - "star": &StarEvent{}, - "status": &StatusEvent{}, - "team": &TeamEvent{}, - "team_add": &TeamAddEvent{}, - "user": &UserEvent{}, - "watch": &WatchEvent{}, - "workflow_dispatch": &WorkflowDispatchEvent{}, - "workflow_job": &WorkflowJobEvent{}, - "workflow_run": &WorkflowRunEvent{}, + "branch_protection_configuration": &BranchProtectionConfigurationEvent{}, + "branch_protection_rule": &BranchProtectionRuleEvent{}, + "check_run": &CheckRunEvent{}, + "check_suite": &CheckSuiteEvent{}, + "code_scanning_alert": &CodeScanningAlertEvent{}, + "commit_comment": &CommitCommentEvent{}, + "content_reference": &ContentReferenceEvent{}, + "create": &CreateEvent{}, + "delete": &DeleteEvent{}, + "dependabot_alert": &DependabotAlertEvent{}, + "deploy_key": &DeployKeyEvent{}, + "deployment": &DeploymentEvent{}, + "deployment_review": &DeploymentReviewEvent{}, + "deployment_status": &DeploymentStatusEvent{}, + "deployment_protection_rule": &DeploymentProtectionRuleEvent{}, + "discussion": &DiscussionEvent{}, + "discussion_comment": &DiscussionCommentEvent{}, + "fork": &ForkEvent{}, + "github_app_authorization": &GitHubAppAuthorizationEvent{}, + "gollum": &GollumEvent{}, + "installation": &InstallationEvent{}, + "installation_repositories": &InstallationRepositoriesEvent{}, + "installation_target": &InstallationTargetEvent{}, + "issue_comment": &IssueCommentEvent{}, + "issues": &IssuesEvent{}, + "label": &LabelEvent{}, + "marketplace_purchase": &MarketplacePurchaseEvent{}, + "member": &MemberEvent{}, + "membership": &MembershipEvent{}, + "merge_group": &MergeGroupEvent{}, + "meta": &MetaEvent{}, + "milestone": &MilestoneEvent{}, + "organization": &OrganizationEvent{}, + "org_block": &OrgBlockEvent{}, + "package": &PackageEvent{}, + "page_build": &PageBuildEvent{}, + "personal_access_token_request": &PersonalAccessTokenRequestEvent{}, + "ping": &PingEvent{}, + "project": &ProjectEvent{}, + "project_card": &ProjectCardEvent{}, + "project_column": &ProjectColumnEvent{}, + "projects_v2": &ProjectV2Event{}, + "projects_v2_item": &ProjectV2ItemEvent{}, + "public": &PublicEvent{}, + "pull_request": &PullRequestEvent{}, + "pull_request_review": &PullRequestReviewEvent{}, + "pull_request_review_comment": &PullRequestReviewCommentEvent{}, + "pull_request_review_thread": &PullRequestReviewThreadEvent{}, + "pull_request_target": &PullRequestTargetEvent{}, + "push": &PushEvent{}, + "repository": &RepositoryEvent{}, + "repository_dispatch": &RepositoryDispatchEvent{}, + "repository_import": &RepositoryImportEvent{}, + "repository_ruleset": &RepositoryRulesetEvent{}, + "repository_vulnerability_alert": &RepositoryVulnerabilityAlertEvent{}, + "release": &ReleaseEvent{}, + "secret_scanning_alert": &SecretScanningAlertEvent{}, + "secret_scanning_alert_location": &SecretScanningAlertLocationEvent{}, + "security_advisory": &SecurityAdvisoryEvent{}, + "security_and_analysis": &SecurityAndAnalysisEvent{}, + "sponsorship": &SponsorshipEvent{}, + "star": &StarEvent{}, + "status": &StatusEvent{}, + "team": &TeamEvent{}, + "team_add": &TeamAddEvent{}, + "user": &UserEvent{}, + "watch": &WatchEvent{}, + "workflow_dispatch": &WorkflowDispatchEvent{}, + "workflow_job": &WorkflowJobEvent{}, + "workflow_run": &WorkflowRunEvent{}, } // Forward mapping of event types to the string names of the structs. messageToTypeName = make(map[string]string, len(eventTypeMapping)) diff --git a/github/messages_test.go b/github/messages_test.go index e04c0b18a7b..be325d504b4 100644 --- a/github/messages_test.go +++ b/github/messages_test.go @@ -264,6 +264,10 @@ func TestParseWebHook(t *testing.T) { payload interface{} messageType string }{ + { + payload: &BranchProtectionConfigurationEvent{}, + messageType: "branch_protection_configuration", + }, { payload: &BranchProtectionRuleEvent{}, messageType: "branch_protection_rule", @@ -480,6 +484,10 @@ func TestParseWebHook(t *testing.T) { payload: &SecretScanningAlertEvent{}, messageType: "secret_scanning_alert", }, + { + payload: &SecretScanningAlertLocationEvent{}, + messageType: "secret_scanning_alert_location", + }, { payload: &SecurityAdvisoryEvent{}, messageType: "security_advisory", From 30739297aa90e281238c12e80e60190c2545b787 Mon Sep 17 00:00:00 2001 From: Aditya Mahendrakar Date: Thu, 24 Oct 2024 06:35:31 -0700 Subject: [PATCH 3/3] remove superfluous response.WriteHeader calls --- github/orgs_codesecurity_configurations_test.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/github/orgs_codesecurity_configurations_test.go b/github/orgs_codesecurity_configurations_test.go index d59b37057ca..e72f9fb976c 100644 --- a/github/orgs_codesecurity_configurations_test.go +++ b/github/orgs_codesecurity_configurations_test.go @@ -382,7 +382,6 @@ func TestOrganizationsService_SetDefaultCodeSecurityConfiguration(t *testing.T) "code_scanning_default_setup": "enabled" } }`) - w.WriteHeader(http.StatusOK) }) got, resp, err := client.Organizations.SetDefaultCodeSecurityConfiguration(ctx, "o", 1, "all") if err != nil { @@ -478,7 +477,6 @@ func TestOrganizationsService_GetCodeSecurityConfigurationForRepository(t *testi "code_scanning_default_setup": "enabled" } }`) - w.WriteHeader(http.StatusOK) }) rc, _, err := client.Organizations.GetCodeSecurityConfigurationForRepository(ctx, "o", "repo8")