Repository: google/go-github (go)

Issue:
Support for registry_package events
According to the [documentation](https://docs.github.com/en/webhooks/webhook-events-and-payloads#registry_package) (and [this](https://docs.github.com/en/webhooks/webhook-events-and-payloads#package)) a Github App wishing to receive events for a new/updated package should expect to receive the package event which is the renamed registry_package event. However, what actually happens is that in the permissions section for a Github App there is only the Registry Packages event available and the webhook request title has the value `registry_package`.

Can we please add support for this?

Pull request:
Add support for registry_package event
as of the time of this writing, the Github documentation describes two events related to packages. One called package and one called registry_package. According to the documentation, users should switch to using the package event instead of the registry_package event. However, when working with the actual permissions and events, there is no package event but there is a RegistryPackage event that can be enabled for a Github App. It looks like the documentation is wrong and the registry_package event was added after the package event and it's the registry_package event that users should expect to receive.

Fixes: #3544.

Patch:
diff --git a/github/event_types.go b/github/event_types.go
index 6a6caf19..b5369865 100644
--- a/github/event_types.go
+++ b/github/event_types.go
@@ -1446,6 +1446,26 @@ type PushEventRepoOwner struct {
 	Email *string `json:"email,omitempty"`
 }
 
+// RegistryPackageEvent represents activity related to GitHub Packages.
+// The Webhook event name is "registry_package".
+//
+// This event is triggered when a GitHub Package is published or updated.
+//
+// GitHub API docs: https://docs.github.com/en/webhooks/webhook-events-and-payloads#registry_package
+type RegistryPackageEvent struct {
+	// Action is the action that was performed.
+	// Can be "published" or "updated".
+	Action          *string       `json:"action,omitempty"`
+	RegistryPackage *Package      `json:"registry_package,omitempty"`
+	Repository      *Repository   `json:"repository,omitempty"`
+	Organization    *Organization `json:"organization,omitempty"`
+	Enterprise      *Enterprise   `json:"enterprise,omitempty"`
+	Sender          *User         `json:"sender,omitempty"`
+
+	// The following fields are only populated by Webhook events.
+	Installation *Installation `json:"installation,omitempty"`
+}
+
 // ReleaseEvent is triggered when a release is published, unpublished, created,
 // edited, deleted, or prereleased.
 // The Webhook event name is "release".
diff --git a/github/github-accessors.go b/github/github-accessors.go
index 9860c8c8..1e244278 100644
--- a/github/github-accessors.go
+++ b/github/github-accessors.go
@@ -20862,6 +20862,62 @@ func (r *RegistrationToken) GetToken() string {
 	return *r.Token
 }
 
+// GetAction returns the Action field if it's non-nil, zero value otherwise.
+func (r *RegistryPackageEvent) GetAction() string {
+	if r == nil || r.Action == nil {
+		return ""
+	}
+	return *r.Action
+}
+
+// GetEnterprise returns the Enterprise field.
+func (r *RegistryPackageEvent) GetEnterprise() *Enterprise {
+	if r == nil {
+		return nil
+	}
+	return r.Enterprise
+}
+
+// GetInstallation returns the Installation field.
+func (r *RegistryPackageEvent) GetInstallation() *Installation {
+	if r == nil {
+		return nil
+	}
+	return r.Installation
+}
+
+// GetOrganization returns the Organization field.
+func (r *RegistryPackageEvent) GetOrganization() *Organization {
+	if r == nil {
+		return nil
+	}
+	return r.Organization
+}
+
+// GetRegistryPackage returns the RegistryPackage field.
+func (r *RegistryPackageEvent) GetRegistryPackage() *Package {
+	if r == nil {
+		return nil
+	}
+	return r.RegistryPackage
+}
+
+// GetRepository returns the Repository field.
+func (r *RegistryPackageEvent) GetRepository() *Repository {
+	if r == nil {
+		return nil
+	}
+	return r.Repository
+}
+
+// GetSender returns the Sender field.
+func (r *RegistryPackageEvent) GetSender() *User {
+	if r == nil {
+		return nil
+	}
+	return r.Sender
+}
+
 // GetBrowserDownloadURL returns the BrowserDownloadURL field if it's non-nil, zero value otherwise.
 func (r *ReleaseAsset) GetBrowserDownloadURL() string {
 	if r == nil || r.BrowserDownloadURL == nil {
diff --git a/github/messages.go b/github/messages.go
index 59b214b3..2b5cce75 100644
--- a/github/messages.go
+++ b/github/messages.go
@@ -95,6 +95,7 @@ var (
 		"pull_request_review_thread":      &PullRequestReviewThreadEvent{},
 		"pull_request_target":             &PullRequestTargetEvent{},
 		"push":                            &PushEvent{},
+		"registry_package":                &RegistryPackageEvent{},
 		"repository":                      &RepositoryEvent{},
 		"repository_dispatch":             &RepositoryDispatchEvent{},
 		"repository_import":               &RepositoryImportEvent{},


Test patch:
diff --git a/github/event_types_test.go b/github/event_types_test.go
index 296c1d35..17dd96d8 100644
--- a/github/event_types_test.go
+++ b/github/event_types_test.go
@@ -8640,6 +8640,135 @@ func TestPingEvent_Marshal(t *testing.T) {
 	testJSONMarshal(t, u, want)
 }
 
+func TestRegistryPackageEvent_Marshal(t *testing.T) {
+	t.Parallel()
+	testJSONMarshal(t, &RegistryPackageEvent{}, "{}")
+
+	u := &RegistryPackageEvent{
+		Action: Ptr("a"),
+		RegistryPackage: &Package{
+			ID:          Ptr(int64(1)),
+			Name:        Ptr("n"),
+			PackageType: Ptr("pt"),
+			HTMLURL:     Ptr("hurl"),
+			CreatedAt:   &Timestamp{referenceTime},
+			UpdatedAt:   &Timestamp{referenceTime},
+			Owner: &User{
+				Login:     Ptr("l"),
+				ID:        Ptr(int64(1)),
+				NodeID:    Ptr("n"),
+				URL:       Ptr("u"),
+				ReposURL:  Ptr("r"),
+				EventsURL: Ptr("e"),
+				AvatarURL: Ptr("a"),
+			},
+			PackageVersion: &PackageVersion{ID: Ptr(int64(1))},
+			Registry:       &PackageRegistry{Name: Ptr("n")},
+		},
+		Repository: &Repository{
+			ID:   Ptr(int64(1)),
+			URL:  Ptr("s"),
+			Name: Ptr("n"),
+		},
+		Organization: &Organization{
+			BillingEmail:                         Ptr("be"),
+			Blog:                                 Ptr("b"),
+			Company:                              Ptr("c"),
+			Email:                                Ptr("e"),
+			TwitterUsername:                      Ptr("tu"),
+			Location:                             Ptr("loc"),
+			Name:                                 Ptr("n"),
+			Description:                          Ptr("d"),
+			IsVerified:                           Ptr(true),
+			HasOrganizationProjects:              Ptr(true),
+			HasRepositoryProjects:                Ptr(true),
+			DefaultRepoPermission:                Ptr("drp"),
+			MembersCanCreateRepos:                Ptr(true),
+			MembersCanCreateInternalRepos:        Ptr(true),
+			MembersCanCreatePrivateRepos:         Ptr(true),
+			MembersCanCreatePublicRepos:          Ptr(false),
+			MembersAllowedRepositoryCreationType: Ptr("marct"),
+			MembersCanCreatePages:                Ptr(true),
+			MembersCanCreatePublicPages:          Ptr(false),
+			MembersCanCreatePrivatePages:         Ptr(true),
+		},
+		Sender: &User{
+			Login:     Ptr("l"),
+			ID:        Ptr(int64(1)),
+			NodeID:    Ptr("n"),
+			URL:       Ptr("u"),
+			ReposURL:  Ptr("r"),
+			EventsURL: Ptr("e"),
+			AvatarURL: Ptr("a"),
+		},
+	}
+
+	want := `{
+		"action": "a",
+		"registry_package": {
+			"id": 1,
+			"name": "n",
+			"package_type": "pt",
+			"html_url": "hurl",
+			"created_at": ` + referenceTimeStr + `,
+			"updated_at": ` + referenceTimeStr + `,
+			"owner": {
+				"login": "l",
+				"id": 1,
+				"node_id": "n",
+				"avatar_url": "a",
+				"url": "u",
+				"events_url": "e",
+				"repos_url": "r"
+			},
+			"package_version": {
+				"id": 1
+			},
+			"registry": {
+				"name": "n"
+			}
+		},
+		"repository": {
+			"id": 1,
+			"name": "n",
+			"url": "s"
+		},
+		"organization": {
+			"name": "n",
+			"company": "c",
+			"blog": "b",
+			"location": "loc",
+			"email": "e",
+			"twitter_username": "tu",
+			"description": "d",
+			"billing_email": "be",
+			"is_verified": true,
+			"has_organization_projects": true,
+			"has_repository_projects": true,
+			"default_repository_permission": "drp",
+			"members_can_create_repositories": true,
+			"members_can_create_public_repositories": false,
+			"members_can_create_private_repositories": true,
+			"members_can_create_internal_repositories": true,
+			"members_allowed_repository_creation_type": "marct",
+			"members_can_create_pages": true,
+			"members_can_create_public_pages": false,
+			"members_can_create_private_pages": true
+		},
+		"sender": {
+			"login": "l",
+			"id": 1,
+			"node_id": "n",
+			"avatar_url": "a",
+			"url": "u",
+			"events_url": "e",
+			"repos_url": "r"
+		}
+	}`
+
+	testJSONMarshal(t, u, want)
+}
+
 func TestRepositoryDispatchEvent_Marshal(t *testing.T) {
 	t.Parallel()
 	testJSONMarshal(t, &RepositoryDispatchEvent{}, "{}")
diff --git a/github/github-accessors_test.go b/github/github-accessors_test.go
index 99011135..8dadb706 100644
--- a/github/github-accessors_test.go
+++ b/github/github-accessors_test.go
@@ -26887,6 +26887,65 @@ func TestRegistrationToken_GetToken(tt *testing.T) {
 	r.GetToken()
 }
 
+func TestRegistryPackageEvent_GetAction(tt *testing.T) {
+	tt.Parallel()
+	var zeroValue string
+	r := &RegistryPackageEvent{Action: &zeroValue}
+	r.GetAction()
+	r = &RegistryPackageEvent{}
+	r.GetAction()
+	r = nil
+	r.GetAction()
+}
+
+func TestRegistryPackageEvent_GetEnterprise(tt *testing.T) {
+	tt.Parallel()
+	r := &RegistryPackageEvent{}
+	r.GetEnterprise()
+	r = nil
+	r.GetEnterprise()
+}
+
+func TestRegistryPackageEvent_GetInstallation(tt *testing.T) {
+	tt.Parallel()
+	r := &RegistryPackageEvent{}
+	r.GetInstallation()
+	r = nil
+	r.GetInstallation()
+}
+
+func TestRegistryPackageEvent_GetOrganization(tt *testing.T) {
+	tt.Parallel()
+	r := &RegistryPackageEvent{}
+	r.GetOrganization()
+	r = nil
+	r.GetOrganization()
+}
+
+func TestRegistryPackageEvent_GetRegistryPackage(tt *testing.T) {
+	tt.Parallel()
+	r := &RegistryPackageEvent{}
+	r.GetRegistryPackage()
+	r = nil
+	r.GetRegistryPackage()
+}
+
+func TestRegistryPackageEvent_GetRepository(tt *testing.T) {
+	tt.Parallel()
+	r := &RegistryPackageEvent{}
+	r.GetRepository()
+	r = nil
+	r.GetRepository()
+}
+
+func TestRegistryPackageEvent_GetSender(tt *testing.T) {
+	tt.Parallel()
+	r := &RegistryPackageEvent{}
+	r.GetSender()
+	r = nil
+	r.GetSender()
+}
+
 func TestReleaseAsset_GetBrowserDownloadURL(tt *testing.T) {
 	tt.Parallel()
 	var zeroValue string
diff --git a/github/messages_test.go b/github/messages_test.go
index e6c3027c..a2b9feac 100644
--- a/github/messages_test.go
+++ b/github/messages_test.go
@@ -459,6 +459,10 @@ func TestParseWebHook(t *testing.T) {
 			payload:     &PushEvent{},
 			messageType: "push",
 		},
+		{
+			payload:     &RegistryPackageEvent{},
+			messageType: "registry_package",
+		},
 		{
 			payload:     &ReleaseEvent{},
 			messageType: "release",
diff --git a/github/repos_hooks_deliveries_test.go b/github/repos_hooks_deliveries_test.go
index 81421c79..6acb7a81 100644
--- a/github/repos_hooks_deliveries_test.go
+++ b/github/repos_hooks_deliveries_test.go
@@ -183,6 +183,7 @@ var hookDeliveryPayloadTypeToStruct = map[string]interface{}{
 	"pull_request_review_thread":     &PullRequestReviewThreadEvent{},
 	"pull_request_target":            &PullRequestTargetEvent{},
 	"push":                           &PushEvent{},
+	"registry_package":               &RegistryPackageEvent{},
 	"release":                        &ReleaseEvent{},
 	"repository":                     &RepositoryEvent{},
 	"repository_dispatch":            &RepositoryDispatchEvent{},