Repository: google/go-github
Pull request #2868 (2023-08-13 10:53:25)

Add support for projects_v2 and projects_v2_item webhook events
Closes https://github.com/google/go-github/issues/2867

Added support for [projects_v2](https://docs.github.com/en/webhooks-and-events/webhooks/webhook-events-and-payloads#projects_v2) and [projects_v2_item](https://docs.github.com/en/webhooks-and-events/webhooks/webhook-events-and-payloads#projects_v2_item) webhook events.

codecov[bot]: ## [Codecov](https://app.codecov.io/gh/google/go-github/pull/2868?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google) Report
> Merging [#2868](https://app.codecov.io/gh/google/go-github/pull/2868?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google) (5f7c8e1) into [master](https://app.codecov.io/gh/google/go-github/commit/899235e0a9d750d6fecf9048a676046d50f9d4a3?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google) (899235e) will **increase** coverage by `0.00%`.
> The diff coverage is `100.00%`.

```diff
@@           Coverage Diff           @@
##           master    #2868   +/-   ##
=======================================
  Coverage   98.06%   98.06%           
=======================================
  Files         138      138           
  Lines       12327    12331    +4     
=======================================
+ Hits        12089    12093    +4     
  Misses        162      162           
  Partials       76       76           
```


| [Files Changed](https://app.codecov.io/gh/google/go-github/pull/2868?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google) | Coverage Δ | |
|---|---|---|
| [github/event\_types.go](https://app.codecov.io/gh/google/go-github/pull/2868?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google#diff-Z2l0aHViL2V2ZW50X3R5cGVzLmdv) | `100.00% <ø> (ø)` | |
| [github/messages.go](https://app.codecov.io/gh/google/go-github/pull/2868?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google#diff-Z2l0aHViL21lc3NhZ2VzLmdv) | `100.00% <ø> (ø)` | |
| [github/event.go](https://app.codecov.io/gh/google/go-github/pull/2868?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google#diff-Z2l0aHViL2V2ZW50Lmdv) | `100.00% <100.00%> (ø)` | |


gmlewis: This PR has significant conflicts with #2865 due to said PR dramatically changing the internals for webhook events (which will hopefully also reduce the maintenance burden and increase the simplicity of future PRs like this one).

So I apologize for the timing.

We can either move forward with this PR and have more work required in #2865 or we can move forward with #2865 then require changes here.

I'm honestly fine either way.

Do you have a preference @nikpivkin ?
Or do you have a preference, @evankanderson?
evankanderson: I'm happy either way; I'll be updating my PR tomorrow probably

Patch:
diff --git a/AUTHORS b/AUTHORS
index 5e40cd1f..a833043b 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -125,6 +125,7 @@ Derek Jobst <derekjobst@gmail.com>
 DeviousLab <deviouslab@gmail.com>
 Dhi Aurrahman <diorahman@rockybars.com>
 Diego Lapiduz <diego.lapiduz@cfpb.gov>
+Diogo Vilela <be0x74a@gmail.com>
 Dmitri Shuralyov <shurcooL@gmail.com>
 dmnlk <seikima2demon@gmail.com>
 Don Petersen <don@donpetersen.net>
diff --git a/github/event.go b/github/event.go
index 2349cb77..7ec46b5a 100644
--- a/github/event.go
+++ b/github/event.go
@@ -105,6 +105,10 @@ func (e *Event) ParsePayload() (payload interface{}, err error) {
 		payload = &ProjectCardEvent{}
 	case "ProjectColumnEvent":
 		payload = &ProjectColumnEvent{}
+	case "ProjectV2Event":
+		payload = &ProjectV2Event{}
+	case "ProjectV2ItemEvent":
+		payload = &ProjectV2ItemEvent{}
 	case "PublicEvent":
 		payload = &PublicEvent{}
 	case "PullRequestEvent":
@@ -133,6 +137,8 @@ func (e *Event) ParsePayload() (payload interface{}, err error) {
 		payload = &SecretScanningAlertEvent{}
 	case "SecurityAdvisoryEvent":
 		payload = &SecurityAdvisoryEvent{}
+	case "SecurityAndAnalysisEvent":
+		payload = &SecurityAndAnalysisEvent{}
 	case "StarEvent":
 		payload = &StarEvent{}
 	case "StatusEvent":
diff --git a/github/event_types.go b/github/event_types.go
index a2413447..c9e97ffa 100644
--- a/github/event_types.go
+++ b/github/event_types.go
@@ -942,6 +942,77 @@ type ProjectColumnEvent struct {
 	Installation *Installation `json:"installation,omitempty"`
 }
 
+// ProjectV2Event is triggered when there is activity relating to an organization-level project.
+// The Webhook event name is "projects_v2".
+//
+// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#projects_v2
+type ProjectV2Event struct {
+	Action     *string     `json:"action,omitempty"`
+	ProjectsV2 *ProjectsV2 `json:"projects_v2,omitempty"`
+
+	// The following fields are only populated by Webhook events.
+	Installation *Installation `json:"installation,omitempty"`
+	Org          *Organization `json:"organization,omitempty"`
+	Sender       *User         `json:"sender,omitempty"`
+}
+
+// ProjectsV2 represents a projects v2 project.
+type ProjectsV2 struct {
+	ID               *int64     `json:"id,omitempty"`
+	NodeID           *string    `json:"node_id,omitempty"`
+	Owner            *User      `json:"owner,omitempty"`
+	Creator          *User      `json:"creator,omitempty"`
+	Title            *string    `json:"title,omitempty"`
+	Description      *string    `json:"description,omitempty"`
+	Public           *bool      `json:"public,omitempty"`
+	ClosedAt         *Timestamp `json:"closed_at,omitempty"`
+	CreatedAt        *Timestamp `json:"created_at,omitempty"`
+	UpdatedAt        *Timestamp `json:"updated_at,omitempty"`
+	DeletedAt        *Timestamp `json:"deleted_at,omitempty"`
+	Number           *int       `json:"number,omitempty"`
+	ShortDescription *string    `json:"short_description,omitempty"`
+	DeletedBy        *User      `json:"deleted_by,omitempty"`
+}
+
+// ProjectV2ItemEvent is triggered when there is activity relating to an item on an organization-level project.
+// The Webhook event name is "projects_v2_item".
+//
+// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#projects_v2_item
+type ProjectV2ItemEvent struct {
+	Action        *string              `json:"action,omitempty"`
+	Changes       *ProjectV2ItemChange `json:"changes,omitempty"`
+	ProjectV2Item *ProjectV2Item       `json:"projects_v2_item,omitempty"`
+
+	// The following fields are only populated by Webhook events.
+	Installation *Installation `json:"installation,omitempty"`
+	Org          *Organization `json:"organization,omitempty"`
+	Sender       *User         `json:"sender,omitempty"`
+}
+
+// ProjectV2ItemChange represents a project v2 item change.
+type ProjectV2ItemChange struct {
+	ArchivedAt *ArchivedAt `json:"archived_at,omitempty"`
+}
+
+// ArchivedAt represents an archiving date change.
+type ArchivedAt struct {
+	From *Timestamp `json:"from,omitempty"`
+	To   *Timestamp `json:"to,omitempty"`
+}
+
+// ProjectsV2 represents an item belonging to a project.
+type ProjectV2Item struct {
+	ID            *int64     `json:"id,omitempty"`
+	NodeID        *string    `json:"node_id,omitempty"`
+	ProjectNodeID *string    `json:"project_node_id,omitempty"`
+	ContentNodeID *string    `json:"content_node_id,omitempty"`
+	ContentType   *string    `json:"content_type,omitempty"`
+	Creator       *User      `json:"creator,omitempty"`
+	CreatedAt     *Timestamp `json:"created_at,omitempty"`
+	UpdatedAt     *Timestamp `json:"updated_at,omitempty"`
+	ArchivedAt    *Timestamp `json:"archived_at,omitempty"`
+}
+
 // PublicEvent is triggered when a private repository is open sourced.
 // According to GitHub: "Without a doubt: the best GitHub event."
 // The Webhook event name is "public".
@@ -1325,6 +1396,31 @@ type SecretScanningAlertEvent struct {
 	Installation *Installation `json:"installation,omitempty"`
 }
 
+// SecurityAndAnalysisEvent is triggered when code security and analysis features
+// are enabled or disabled for a repository.
+//
+// GitHub API docs: https://docs.github.com/en/webhooks-and-events/webhooks/webhook-events-and-payloads#security_and_analysis
+type SecurityAndAnalysisEvent struct {
+	Changes      *SecurityAndAnalysisChange `json:"changes,omitempty"`
+	Enterprise   *Enterprise                `json:"enterprise,omitempty"`
+	Installation *Installation              `json:"installation,omitempty"`
+	Organization *Organization              `json:"organization,omitempty"`
+	Repository   *Repository                `json:"repository,omitempty"`
+	Sender       *User                      `json:"sender,omitempty"`
+}
+
+// SecurityAndAnalysisChange represents the changes when security and analysis
+// features are enabled or disabled for a repository.
+type SecurityAndAnalysisChange struct {
+	From *SecurityAndAnalysisChangeFrom `json:"from,omitempty"`
+}
+
+// SecurityAndAnalysisChangeFrom represents which change was made when security
+// and analysis features are enabled or disabled for a repository.
+type SecurityAndAnalysisChangeFrom struct {
+	SecurityAndAnalysis *SecurityAndAnalysis `json:"security_and_analysis,omitempty"`
+}
+
 // StarEvent is triggered when a star is added or removed from a repository.
 // The Webhook event name is "star".
 //
diff --git a/github/github-accessors.go b/github/github-accessors.go
index 3f665ede..1fabd520 100644
--- a/github/github-accessors.go
+++ b/github/github-accessors.go
@@ -854,6 +854,22 @@ func (a *AppConfig) GetWebhookSecret() string {
 	return *a.WebhookSecret
 }
 
+// GetFrom returns the From field if it's non-nil, zero value otherwise.
+func (a *ArchivedAt) GetFrom() Timestamp {
+	if a == nil || a.From == nil {
+		return Timestamp{}
+	}
+	return *a.From
+}
+
+// GetTo returns the To field if it's non-nil, zero value otherwise.
+func (a *ArchivedAt) GetTo() Timestamp {
+	if a == nil || a.To == nil {
+		return Timestamp{}
+	}
+	return *a.To
+}
+
 // GetArchiveDownloadURL returns the ArchiveDownloadURL field if it's non-nil, zero value otherwise.
 func (a *Artifact) GetArchiveDownloadURL() string {
 	if a == nil || a.ArchiveDownloadURL == nil {
@@ -14374,6 +14390,286 @@ func (p *ProjectPermissionLevel) GetUser() *User {
 	return p.User
 }
 
+// GetClosedAt returns the ClosedAt field if it's non-nil, zero value otherwise.
+func (p *ProjectsV2) GetClosedAt() Timestamp {
+	if p == nil || p.ClosedAt == nil {
+		return Timestamp{}
+	}
+	return *p.ClosedAt
+}
+
+// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise.
+func (p *ProjectsV2) GetCreatedAt() Timestamp {
+	if p == nil || p.CreatedAt == nil {
+		return Timestamp{}
+	}
+	return *p.CreatedAt
+}
+
+// GetCreator returns the Creator field.
+func (p *ProjectsV2) GetCreator() *User {
+	if p == nil {
+		return nil
+	}
+	return p.Creator
+}
+
+// GetDeletedAt returns the DeletedAt field if it's non-nil, zero value otherwise.
+func (p *ProjectsV2) GetDeletedAt() Timestamp {
+	if p == nil || p.DeletedAt == nil {
+		return Timestamp{}
+	}
+	return *p.DeletedAt
+}
+
+// GetDeletedBy returns the DeletedBy field.
+func (p *ProjectsV2) GetDeletedBy() *User {
+	if p == nil {
+		return nil
+	}
+	return p.DeletedBy
+}
+
+// GetDescription returns the Description field if it's non-nil, zero value otherwise.
+func (p *ProjectsV2) GetDescription() string {
+	if p == nil || p.Description == nil {
+		return ""
+	}
+	return *p.Description
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (p *ProjectsV2) GetID() int64 {
+	if p == nil || p.ID == nil {
+		return 0
+	}
+	return *p.ID
+}
+
+// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise.
+func (p *ProjectsV2) GetNodeID() string {
+	if p == nil || p.NodeID == nil {
+		return ""
+	}
+	return *p.NodeID
+}
+
+// GetNumber returns the Number field if it's non-nil, zero value otherwise.
+func (p *ProjectsV2) GetNumber() int {
+	if p == nil || p.Number == nil {
+		return 0
+	}
+	return *p.Number
+}
+
+// GetOwner returns the Owner field.
+func (p *ProjectsV2) GetOwner() *User {
+	if p == nil {
+		return nil
+	}
+	return p.Owner
+}
+
+// GetPublic returns the Public field if it's non-nil, zero value otherwise.
+func (p *ProjectsV2) GetPublic() bool {
+	if p == nil || p.Public == nil {
+		return false
+	}
+	return *p.Public
+}
+
+// GetShortDescription returns the ShortDescription field if it's non-nil, zero value otherwise.
+func (p *ProjectsV2) GetShortDescription() string {
+	if p == nil || p.ShortDescription == nil {
+		return ""
+	}
+	return *p.ShortDescription
+}
+
+// GetTitle returns the Title field if it's non-nil, zero value otherwise.
+func (p *ProjectsV2) GetTitle() string {
+	if p == nil || p.Title == nil {
+		return ""
+	}
+	return *p.Title
+}
+
+// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise.
+func (p *ProjectsV2) GetUpdatedAt() Timestamp {
+	if p == nil || p.UpdatedAt == nil {
+		return Timestamp{}
+	}
+	return *p.UpdatedAt
+}
+
+// GetAction returns the Action field if it's non-nil, zero value otherwise.
+func (p *ProjectV2Event) GetAction() string {
+	if p == nil || p.Action == nil {
+		return ""
+	}
+	return *p.Action
+}
+
+// GetInstallation returns the Installation field.
+func (p *ProjectV2Event) GetInstallation() *Installation {
+	if p == nil {
+		return nil
+	}
+	return p.Installation
+}
+
+// GetOrg returns the Org field.
+func (p *ProjectV2Event) GetOrg() *Organization {
+	if p == nil {
+		return nil
+	}
+	return p.Org
+}
+
+// GetProjectsV2 returns the ProjectsV2 field.
+func (p *ProjectV2Event) GetProjectsV2() *ProjectsV2 {
+	if p == nil {
+		return nil
+	}
+	return p.ProjectsV2
+}
+
+// GetSender returns the Sender field.
+func (p *ProjectV2Event) GetSender() *User {
+	if p == nil {
+		return nil
+	}
+	return p.Sender
+}
+
+// GetArchivedAt returns the ArchivedAt field if it's non-nil, zero value otherwise.
+func (p *ProjectV2Item) GetArchivedAt() Timestamp {
+	if p == nil || p.ArchivedAt == nil {
+		return Timestamp{}
+	}
+	return *p.ArchivedAt
+}
+
+// GetContentNodeID returns the ContentNodeID field if it's non-nil, zero value otherwise.
+func (p *ProjectV2Item) GetContentNodeID() string {
+	if p == nil || p.ContentNodeID == nil {
+		return ""
+	}
+	return *p.ContentNodeID
+}
+
+// GetContentType returns the ContentType field if it's non-nil, zero value otherwise.
+func (p *ProjectV2Item) GetContentType() string {
+	if p == nil || p.ContentType == nil {
+		return ""
+	}
+	return *p.ContentType
+}
+
+// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise.
+func (p *ProjectV2Item) GetCreatedAt() Timestamp {
+	if p == nil || p.CreatedAt == nil {
+		return Timestamp{}
+	}
+	return *p.CreatedAt
+}
+
+// GetCreator returns the Creator field.
+func (p *ProjectV2Item) GetCreator() *User {
+	if p == nil {
+		return nil
+	}
+	return p.Creator
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (p *ProjectV2Item) GetID() int64 {
+	if p == nil || p.ID == nil {
+		return 0
+	}
+	return *p.ID
+}
+
+// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise.
+func (p *ProjectV2Item) GetNodeID() string {
+	if p == nil || p.NodeID == nil {
+		return ""
+	}
+	return *p.NodeID
+}
+
+// GetProjectNodeID returns the ProjectNodeID field if it's non-nil, zero value otherwise.
+func (p *ProjectV2Item) GetProjectNodeID() string {
+	if p == nil || p.ProjectNodeID == nil {
+		return ""
+	}
+	return *p.ProjectNodeID
+}
+
+// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise.
+func (p *ProjectV2Item) GetUpdatedAt() Timestamp {
+	if p == nil || p.UpdatedAt == nil {
+		return Timestamp{}
+	}
+	return *p.UpdatedAt
+}
+
+// GetArchivedAt returns the ArchivedAt field.
+func (p *ProjectV2ItemChange) GetArchivedAt() *ArchivedAt {
+	if p == nil {
+		return nil
+	}
+	return p.ArchivedAt
+}
+
+// GetAction returns the Action field if it's non-nil, zero value otherwise.
+func (p *ProjectV2ItemEvent) GetAction() string {
+	if p == nil || p.Action == nil {
+		return ""
+	}
+	return *p.Action
+}
+
+// GetChanges returns the Changes field.
+func (p *ProjectV2ItemEvent) GetChanges() *ProjectV2ItemChange {
+	if p == nil {
+		return nil
+	}
+	return p.Changes
+}
+
+// GetInstallation returns the Installation field.
+func (p *ProjectV2ItemEvent) GetInstallation() *Installation {
+	if p == nil {
+		return nil
+	}
+	return p.Installation
+}
+
+// GetOrg returns the Org field.
+func (p *ProjectV2ItemEvent) GetOrg() *Organization {
+	if p == nil {
+		return nil
+	}
+	return p.Org
+}
+
+// GetProjectV2Item returns the ProjectV2Item field.
+func (p *ProjectV2ItemEvent) GetProjectV2Item() *ProjectV2Item {
+	if p == nil {
+		return nil
+	}
+	return p.ProjectV2Item
+}
+
+// GetSender returns the Sender field.
+func (p *ProjectV2ItemEvent) GetSender() *User {
+	if p == nil {
+		return nil
+	}
+	return p.Sender
+}
+
 // GetAllowDeletions returns the AllowDeletions field.
 func (p *Protection) GetAllowDeletions() *AllowDeletions {
 	if p == nil {
@@ -20270,6 +20566,70 @@ func (s *SecurityAndAnalysis) GetSecretScanningPushProtection() *SecretScanningP
 	return s.SecretScanningPushProtection
 }
 
+// GetFrom returns the From field.
+func (s *SecurityAndAnalysisChange) GetFrom() *SecurityAndAnalysisChangeFrom {
+	if s == nil {
+		return nil
+	}
+	return s.From
+}
+
+// GetSecurityAndAnalysis returns the SecurityAndAnalysis field.
+func (s *SecurityAndAnalysisChangeFrom) GetSecurityAndAnalysis() *SecurityAndAnalysis {
+	if s == nil {
+		return nil
+	}
+	return s.SecurityAndAnalysis
+}
+
+// GetChanges returns the Changes field.
+func (s *SecurityAndAnalysisEvent) GetChanges() *SecurityAndAnalysisChange {
+	if s == nil {
+		return nil
+	}
+	return s.Changes
+}
+
+// GetEnterprise returns the Enterprise field.
+func (s *SecurityAndAnalysisEvent) GetEnterprise() *Enterprise {
+	if s == nil {
+		return nil
+	}
+	return s.Enterprise
+}
+
+// GetInstallation returns the Installation field.
+func (s *SecurityAndAnalysisEvent) GetInstallation() *Installation {
+	if s == nil {
+		return nil
+	}
+	return s.Installation
+}
+
+// GetOrganization returns the Organization field.
+func (s *SecurityAndAnalysisEvent) GetOrganization() *Organization {
+	if s == nil {
+		return nil
+	}
+	return s.Organization
+}
+
+// GetRepository returns the Repository field.
+func (s *SecurityAndAnalysisEvent) GetRepository() *Repository {
+	if s == nil {
+		return nil
+	}
+	return s.Repository
+}
+
+// GetSender returns the Sender field.
+func (s *SecurityAndAnalysisEvent) GetSender() *User {
+	if s == nil {
+		return nil
+	}
+	return s.Sender
+}
+
 // GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise.
 func (s *SelectedReposList) GetTotalCount() int {
 	if s == nil || s.TotalCount == nil {
diff --git a/github/github.go b/github/github.go
index 1b41ffdc..79960835 100644
--- a/github/github.go
+++ b/github/github.go
@@ -179,36 +179,37 @@ type Client struct {
 	common service // Reuse a single struct instead of allocating one for each service on the heap.
 
 	// Services used for talking to different parts of the GitHub API.
-	Actions        *ActionsService
-	Activity       *ActivityService
-	Admin          *AdminService
-	Apps           *AppsService
-	Authorizations *AuthorizationsService
-	Billing        *BillingService
-	Checks         *ChecksService
-	CodeScanning   *CodeScanningService
-	Codespaces     *CodespacesService
-	Dependabot     *DependabotService
-	Enterprise     *EnterpriseService
-	Gists          *GistsService
-	Git            *GitService
-	Gitignores     *GitignoresService
-	Interactions   *InteractionsService
-	IssueImport    *IssueImportService
-	Issues         *IssuesService
-	Licenses       *LicensesService
-	Marketplace    *MarketplaceService
-	Migrations     *MigrationService
-	Organizations  *OrganizationsService
-	Projects       *ProjectsService
-	PullRequests   *PullRequestsService
-	Reactions      *ReactionsService
-	Repositories   *RepositoriesService
-	SCIM           *SCIMService
-	Search         *SearchService
-	SecretScanning *SecretScanningService
-	Teams          *TeamsService
-	Users          *UsersService
+	Actions            *ActionsService
+	Activity           *ActivityService
+	Admin              *AdminService
+	Apps               *AppsService
+	Authorizations     *AuthorizationsService
+	Billing            *BillingService
+	Checks             *ChecksService
+	CodeScanning       *CodeScanningService
+	Codespaces         *CodespacesService
+	Dependabot         *DependabotService
+	Enterprise         *EnterpriseService
+	Gists              *GistsService
+	Git                *GitService
+	Gitignores         *GitignoresService
+	Interactions       *InteractionsService
+	IssueImport        *IssueImportService
+	Issues             *IssuesService
+	Licenses           *LicensesService
+	Marketplace        *MarketplaceService
+	Migrations         *MigrationService
+	Organizations      *OrganizationsService
+	Projects           *ProjectsService
+	PullRequests       *PullRequestsService
+	Reactions          *ReactionsService
+	Repositories       *RepositoriesService
+	SCIM               *SCIMService
+	Search             *SearchService
+	SecretScanning     *SecretScanningService
+	SecurityAdvisories *SecurityAdvisoriesService
+	Teams              *TeamsService
+	Users              *UsersService
 }
 
 type service struct {
@@ -346,6 +347,7 @@ func NewClient(httpClient *http.Client) *Client {
 	c.SCIM = (*SCIMService)(&c.common)
 	c.Search = (*SearchService)(&c.common)
 	c.SecretScanning = (*SecretScanningService)(&c.common)
+	c.SecurityAdvisories = (*SecurityAdvisoriesService)(&c.common)
 	c.Teams = (*TeamsService)(&c.common)
 	c.Users = (*UsersService)(&c.common)
 	return c
diff --git a/github/messages.go b/github/messages.go
index 929587d3..e15442e5 100644
--- a/github/messages.go
+++ b/github/messages.go
@@ -82,6 +82,8 @@ var (
 		"project":                        "ProjectEvent",
 		"project_card":                   "ProjectCardEvent",
 		"project_column":                 "ProjectColumnEvent",
+		"projects_v2":                    "ProjectV2Event",
+		"projects_v2_item":               "ProjectV2ItemEvent",
 		"public":                         "PublicEvent",
 		"pull_request":                   "PullRequestEvent",
 		"pull_request_review":            "PullRequestReviewEvent",
@@ -96,6 +98,7 @@ var (
 		"release":                        "ReleaseEvent",
 		"secret_scanning_alert":          "SecretScanningAlertEvent",
 		"security_advisory":              "SecurityAdvisoryEvent",
+		"security_and_analysis":          "SecurityAndAnalysisEvent",
 		"star":                           "StarEvent",
 		"status":                         "StatusEvent",
 		"team":                           "TeamEvent",
diff --git a/github/security_advisories.go b/github/security_advisories.go
new file mode 100644
index 00000000..a75fce54
--- /dev/null
+++ b/github/security_advisories.go
@@ -0,0 +1,37 @@
+// Copyright 2023 The go-github AUTHORS. All rights reserved.
+//
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package github
+
+import (
+	"context"
+	"fmt"
+)
+
+type SecurityAdvisoriesService service
+
+// RequestCVE requests a Common Vulnerabilities and Exposures (CVE) for a repository security advisory.
+// The ghsaID is the GitHub Security Advisory identifier of the advisory.
+//
+// GitHub API docs: https://docs.github.com/en/rest/security-advisories/repository-advisories#request-a-cve-for-a-repository-security-advisory
+func (s *SecurityAdvisoriesService) RequestCVE(ctx context.Context, owner, repo, ghsaID string) (*Response, error) {
+	url := fmt.Sprintf("repos/%v/%v/security-advisories/%v/cve", owner, repo, ghsaID)
+
+	req, err := s.client.NewRequest("POST", url, nil)
+	if err != nil {
+		return nil, err
+	}
+
+	resp, err := s.client.Do(ctx, req, nil)
+	if err != nil {
+		if _, ok := err.(*AcceptedError); ok {
+			return resp, nil
+		}
+
+		return resp, err
+	}
+
+	return resp, nil
+}


Test patch:
diff --git a/github/event_types_test.go b/github/event_types_test.go
index 8d6a8b95..c1cb4d96 100644
--- a/github/event_types_test.go
+++ b/github/event_types_test.go
@@ -14092,6 +14092,396 @@ func TestProjectColumnEvent_Marshal(t *testing.T) {
 	testJSONMarshal(t, u, want)
 }
 
+func TestProjectV2Event_Marshal(t *testing.T) {
+	testJSONMarshal(t, &ProjectV2Event{}, "{}")
+
+	u := &ProjectV2Event{
+		Action: String("a"),
+		ProjectsV2: &ProjectsV2{
+			ID:     Int64(1),
+			NodeID: String("nid"),
+			Owner: &User{
+				Login:     String("l"),
+				ID:        Int64(1),
+				NodeID:    String("n"),
+				URL:       String("u"),
+				ReposURL:  String("r"),
+				EventsURL: String("e"),
+				AvatarURL: String("a"),
+			},
+			Creator: &User{
+				Login:     String("l"),
+				ID:        Int64(1),
+				NodeID:    String("n"),
+				URL:       String("u"),
+				ReposURL:  String("r"),
+				EventsURL: String("e"),
+				AvatarURL: String("a"),
+			},
+			Title:            String("t"),
+			Description:      String("d"),
+			Public:           Bool(true),
+			ClosedAt:         &Timestamp{referenceTime},
+			CreatedAt:        &Timestamp{referenceTime},
+			UpdatedAt:        &Timestamp{referenceTime},
+			DeletedAt:        &Timestamp{referenceTime},
+			Number:           Int(1),
+			ShortDescription: String("sd"),
+			DeletedBy: &User{
+				Login:     String("l"),
+				ID:        Int64(1),
+				NodeID:    String("n"),
+				URL:       String("u"),
+				ReposURL:  String("r"),
+				EventsURL: String("e"),
+				AvatarURL: String("a"),
+			},
+		},
+		Org: &Organization{
+			BillingEmail:                         String("be"),
+			Blog:                                 String("b"),
+			Company:                              String("c"),
+			Email:                                String("e"),
+			TwitterUsername:                      String("tu"),
+			Location:                             String("loc"),
+			Name:                                 String("n"),
+			Description:                          String("d"),
+			IsVerified:                           Bool(true),
+			HasOrganizationProjects:              Bool(true),
+			HasRepositoryProjects:                Bool(true),
+			DefaultRepoPermission:                String("drp"),
+			MembersCanCreateRepos:                Bool(true),
+			MembersCanCreateInternalRepos:        Bool(true),
+			MembersCanCreatePrivateRepos:         Bool(true),
+			MembersCanCreatePublicRepos:          Bool(false),
+			MembersAllowedRepositoryCreationType: String("marct"),
+			MembersCanCreatePages:                Bool(true),
+			MembersCanCreatePublicPages:          Bool(false),
+			MembersCanCreatePrivatePages:         Bool(true),
+		},
+		Sender: &User{
+			Login:     String("l"),
+			ID:        Int64(1),
+			NodeID:    String("n"),
+			URL:       String("u"),
+			ReposURL:  String("r"),
+			EventsURL: String("e"),
+			AvatarURL: String("a"),
+		},
+		Installation: &Installation{
+			ID:       Int64(1),
+			NodeID:   String("nid"),
+			AppID:    Int64(1),
+			AppSlug:  String("as"),
+			TargetID: Int64(1),
+			Account: &User{
+				Login:           String("l"),
+				ID:              Int64(1),
+				URL:             String("u"),
+				AvatarURL:       String("a"),
+				GravatarID:      String("g"),
+				Name:            String("n"),
+				Company:         String("c"),
+				Blog:            String("b"),
+				Location:        String("l"),
+				Email:           String("e"),
+				Hireable:        Bool(true),
+				Bio:             String("b"),
+				TwitterUsername: String("t"),
+				PublicRepos:     Int(1),
+				Followers:       Int(1),
+				Following:       Int(1),
+				CreatedAt:       &Timestamp{referenceTime},
+				SuspendedAt:     &Timestamp{referenceTime},
+			},
+		},
+	}
+
+	want := `{
+		"action": "a",
+		"projects_v2": {
+			"id": 1,
+			"node_id": "nid",
+			"owner": {
+				"login": "l",
+				"id": 1,
+				"node_id": "n",
+				"avatar_url": "a",
+				"url": "u",
+				"events_url": "e",
+				"repos_url": "r"
+			},
+			"creator": {
+				"login": "l",
+				"id": 1,
+				"node_id": "n",
+				"avatar_url": "a",
+				"url": "u",
+				"events_url": "e",
+				"repos_url": "r"
+			},
+			"title": "t",
+			"description": "d",
+			"public": true,
+			"closed_at": ` + referenceTimeStr + `,
+			"created_at": ` + referenceTimeStr + `,
+			"updated_at": ` + referenceTimeStr + `,
+			"deleted_at": ` + referenceTimeStr + `,
+			"number": 1,
+			"short_description": "sd",
+			"deleted_by": {
+				"login": "l",
+				"id": 1,
+				"node_id": "n",
+				"avatar_url": "a",
+				"url": "u",
+				"events_url": "e",
+				"repos_url": "r"
+			}
+		},
+		"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"
+		},
+		"installation": {
+			"id": 1,
+			"node_id": "nid",
+			"app_id": 1,
+			"app_slug": "as",
+			"target_id": 1,
+			"account": {
+				"login": "l",
+				"id": 1,
+				"avatar_url": "a",
+				"gravatar_id": "g",
+				"name": "n",
+				"company": "c",
+				"blog": "b",
+				"location": "l",
+				"email": "e",
+				"hireable": true,
+				"bio": "b",
+				"twitter_username": "t",
+				"public_repos": 1,
+				"followers": 1,
+				"following": 1,
+				"created_at": ` + referenceTimeStr + `,
+				"suspended_at": ` + referenceTimeStr + `,
+				"url": "u"
+			}
+		}
+	}`
+
+	testJSONMarshal(t, u, want)
+}
+
+func TestProjectV2ItemEvent_Marshal(t *testing.T) {
+	testJSONMarshal(t, &ProjectV2ItemEvent{}, "{}")
+
+	u := &ProjectV2ItemEvent{
+		Action: String("a"),
+		Changes: &ProjectV2ItemChange{
+			ArchivedAt: &ArchivedAt{
+				From: &Timestamp{referenceTime},
+				To:   &Timestamp{referenceTime},
+			},
+		},
+		ProjectV2Item: &ProjectV2Item{
+			ID:            Int64(1),
+			NodeID:        String("nid"),
+			ProjectNodeID: String("pnid"),
+			ContentNodeID: String("cnid"),
+			ContentType:   String("ct"),
+			Creator: &User{
+				Login:     String("l"),
+				ID:        Int64(1),
+				NodeID:    String("n"),
+				URL:       String("u"),
+				ReposURL:  String("r"),
+				EventsURL: String("e"),
+				AvatarURL: String("a"),
+			},
+			CreatedAt:  &Timestamp{referenceTime},
+			UpdatedAt:  &Timestamp{referenceTime},
+			ArchivedAt: &Timestamp{referenceTime},
+		},
+		Org: &Organization{
+			BillingEmail:                         String("be"),
+			Blog:                                 String("b"),
+			Company:                              String("c"),
+			Email:                                String("e"),
+			TwitterUsername:                      String("tu"),
+			Location:                             String("loc"),
+			Name:                                 String("n"),
+			Description:                          String("d"),
+			IsVerified:                           Bool(true),
+			HasOrganizationProjects:              Bool(true),
+			HasRepositoryProjects:                Bool(true),
+			DefaultRepoPermission:                String("drp"),
+			MembersCanCreateRepos:                Bool(true),
+			MembersCanCreateInternalRepos:        Bool(true),
+			MembersCanCreatePrivateRepos:         Bool(true),
+			MembersCanCreatePublicRepos:          Bool(false),
+			MembersAllowedRepositoryCreationType: String("marct"),
+			MembersCanCreatePages:                Bool(true),
+			MembersCanCreatePublicPages:          Bool(false),
+			MembersCanCreatePrivatePages:         Bool(true),
+		},
+		Sender: &User{
+			Login:     String("l"),
+			ID:        Int64(1),
+			NodeID:    String("n"),
+			URL:       String("u"),
+			ReposURL:  String("r"),
+			EventsURL: String("e"),
+			AvatarURL: String("a"),
+		},
+		Installation: &Installation{
+			ID:       Int64(1),
+			NodeID:   String("nid"),
+			AppID:    Int64(1),
+			AppSlug:  String("as"),
+			TargetID: Int64(1),
+			Account: &User{
+				Login:           String("l"),
+				ID:              Int64(1),
+				URL:             String("u"),
+				AvatarURL:       String("a"),
+				GravatarID:      String("g"),
+				Name:            String("n"),
+				Company:         String("c"),
+				Blog:            String("b"),
+				Location:        String("l"),
+				Email:           String("e"),
+				Hireable:        Bool(true),
+				Bio:             String("b"),
+				TwitterUsername: String("t"),
+				PublicRepos:     Int(1),
+				Followers:       Int(1),
+				Following:       Int(1),
+				CreatedAt:       &Timestamp{referenceTime},
+				SuspendedAt:     &Timestamp{referenceTime},
+			},
+		},
+	}
+
+	want := `{
+		"action":  "a",
+		"changes": {
+			"archived_at": {
+				"from": ` + referenceTimeStr + `,
+				"to": ` + referenceTimeStr + `
+			}
+		},
+		"projects_v2_item": {
+			"id": 1,
+			"node_id": "nid",
+			"project_node_id": "pnid",
+			"content_node_id": "cnid",
+			"content_type": "ct",
+			"creator":  {
+				"login": "l",
+				"id": 1,
+				"node_id": "n",
+				"avatar_url": "a",
+				"url": "u",
+				"events_url": "e",
+				"repos_url": "r"
+			},
+			"created_at": ` + referenceTimeStr + `,
+			"updated_at": ` + referenceTimeStr + `,
+			"archived_at": ` + referenceTimeStr + `
+		},
+		"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"
+		},
+		"installation": {
+			"id": 1,
+			"node_id": "nid",
+			"app_id": 1,
+			"app_slug": "as",
+			"target_id": 1,
+			"account": {
+				"login": "l",
+				"id": 1,
+				"avatar_url": "a",
+				"gravatar_id": "g",
+				"name": "n",
+				"company": "c",
+				"blog": "b",
+				"location": "l",
+				"email": "e",
+				"hireable": true,
+				"bio": "b",
+				"twitter_username": "t",
+				"public_repos": 1,
+				"followers": 1,
+				"following": 1,
+				"created_at": ` + referenceTimeStr + `,
+				"suspended_at": ` + referenceTimeStr + `,
+				"url": "u"
+			}
+		}
+	}`
+
+	testJSONMarshal(t, u, want)
+}
+
 func TestPullRequestEvent_Marshal(t *testing.T) {
 	testJSONMarshal(t, &PullRequestEvent{}, "{}")
 
@@ -14732,14 +15122,321 @@ func TestPullRequestReviewThreadEvent_Marshal(t *testing.T) {
 	u := &PullRequestReviewThreadEvent{
 		Action:      String("a"),
 		PullRequest: &PullRequest{ID: Int64(1)},
-		Thread: &PullRequestThread{
-			Comments: []*PullRequestComment{{ID: Int64(1)}, {ID: Int64(2)}},
+		Thread: &PullRequestThread{
+			Comments: []*PullRequestComment{{ID: Int64(1)}, {ID: Int64(2)}},
+		},
+		Repo: &Repository{
+			ID:   Int64(1),
+			URL:  String("s"),
+			Name: String("n"),
+		},
+		Sender: &User{
+			Login:     String("l"),
+			ID:        Int64(1),
+			NodeID:    String("n"),
+			URL:       String("u"),
+			ReposURL:  String("r"),
+			EventsURL: String("e"),
+			AvatarURL: String("a"),
+		},
+		Installation: &Installation{
+			ID:       Int64(1),
+			NodeID:   String("nid"),
+			AppID:    Int64(1),
+			AppSlug:  String("as"),
+			TargetID: Int64(1),
+			Account: &User{
+				Login:           String("l"),
+				ID:              Int64(1),
+				URL:             String("u"),
+				AvatarURL:       String("a"),
+				GravatarID:      String("g"),
+				Name:            String("n"),
+				Company:         String("c"),
+				Blog:            String("b"),
+				Location:        String("l"),
+				Email:           String("e"),
+				Hireable:        Bool(true),
+				Bio:             String("b"),
+				TwitterUsername: String("t"),
+				PublicRepos:     Int(1),
+				Followers:       Int(1),
+				Following:       Int(1),
+				CreatedAt:       &Timestamp{referenceTime},
+				SuspendedAt:     &Timestamp{referenceTime},
+			},
+			AccessTokensURL:     String("atu"),
+			RepositoriesURL:     String("ru"),
+			HTMLURL:             String("hu"),
+			TargetType:          String("tt"),
+			SingleFileName:      String("sfn"),
+			RepositorySelection: String("rs"),
+			Events:              []string{"e"},
+			SingleFilePaths:     []string{"s"},
+			Permissions: &InstallationPermissions{
+				Actions:                       String("a"),
+				Administration:                String("ad"),
+				Checks:                        String("c"),
+				Contents:                      String("co"),
+				ContentReferences:             String("cr"),
+				Deployments:                   String("d"),
+				Environments:                  String("e"),
+				Issues:                        String("i"),
+				Metadata:                      String("md"),
+				Members:                       String("m"),
+				OrganizationAdministration:    String("oa"),
+				OrganizationHooks:             String("oh"),
+				OrganizationPlan:              String("op"),
+				OrganizationPreReceiveHooks:   String("opr"),
+				OrganizationProjects:          String("op"),
+				OrganizationSecrets:           String("os"),
+				OrganizationSelfHostedRunners: String("osh"),
+				OrganizationUserBlocking:      String("oub"),
+				Packages:                      String("pkg"),
+				Pages:                         String("pg"),
+				PullRequests:                  String("pr"),
+				RepositoryHooks:               String("rh"),
+				RepositoryProjects:            String("rp"),
+				RepositoryPreReceiveHooks:     String("rprh"),
+				Secrets:                       String("s"),
+				SecretScanningAlerts:          String("ssa"),
+				SecurityEvents:                String("se"),
+				SingleFile:                    String("sf"),
+				Statuses:                      String("s"),
+				TeamDiscussions:               String("td"),
+				VulnerabilityAlerts:           String("va"),
+				Workflows:                     String("w"),
+			},
+			CreatedAt:              &Timestamp{referenceTime},
+			UpdatedAt:              &Timestamp{referenceTime},
+			HasMultipleSingleFiles: Bool(false),
+			SuspendedBy: &User{
+				Login:           String("l"),
+				ID:              Int64(1),
+				URL:             String("u"),
+				AvatarURL:       String("a"),
+				GravatarID:      String("g"),
+				Name:            String("n"),
+				Company:         String("c"),
+				Blog:            String("b"),
+				Location:        String("l"),
+				Email:           String("e"),
+				Hireable:        Bool(true),
+				Bio:             String("b"),
+				TwitterUsername: String("t"),
+				PublicRepos:     Int(1),
+				Followers:       Int(1),
+				Following:       Int(1),
+				CreatedAt:       &Timestamp{referenceTime},
+				SuspendedAt:     &Timestamp{referenceTime},
+			},
+			SuspendedAt: &Timestamp{referenceTime},
+		},
+	}
+
+	want := `{
+		"action": "a",
+		"pull_request": {
+			"id": 1
+		},
+		"thread": {
+			"comments": [
+				{
+					"id": 1
+				},
+				{
+					"id": 2
+				}
+			]
+		},
+		"repository": {
+			"id": 1,
+			"name": "n",
+			"url": "s"
+		},
+		"sender": {
+			"login": "l",
+			"id": 1,
+			"node_id": "n",
+			"avatar_url": "a",
+			"url": "u",
+			"events_url": "e",
+			"repos_url": "r"
+		},
+		"installation": {
+			"id": 1,
+			"node_id": "nid",
+			"app_id": 1,
+			"app_slug": "as",
+			"target_id": 1,
+			"account": {
+				"login": "l",
+				"id": 1,
+				"avatar_url": "a",
+				"gravatar_id": "g",
+				"name": "n",
+				"company": "c",
+				"blog": "b",
+				"location": "l",
+				"email": "e",
+				"hireable": true,
+				"bio": "b",
+				"twitter_username": "t",
+				"public_repos": 1,
+				"followers": 1,
+				"following": 1,
+				"created_at": ` + referenceTimeStr + `,
+				"suspended_at": ` + referenceTimeStr + `,
+				"url": "u"
+			},
+			"access_tokens_url": "atu",
+			"repositories_url": "ru",
+			"html_url": "hu",
+			"target_type": "tt",
+			"single_file_name": "sfn",
+			"repository_selection": "rs",
+			"events": [
+				"e"
+			],
+			"single_file_paths": [
+				"s"
+			],
+			"permissions": {
+				"actions": "a",
+				"administration": "ad",
+				"checks": "c",
+				"contents": "co",
+				"content_references": "cr",
+				"deployments": "d",
+				"environments": "e",
+				"issues": "i",
+				"metadata": "md",
+				"members": "m",
+				"organization_administration": "oa",
+				"organization_hooks": "oh",
+				"organization_plan": "op",
+				"organization_pre_receive_hooks": "opr",
+				"organization_projects": "op",
+				"organization_secrets": "os",
+				"organization_self_hosted_runners": "osh",
+				"organization_user_blocking": "oub",
+				"packages": "pkg",
+				"pages": "pg",
+				"pull_requests": "pr",
+				"repository_hooks": "rh",
+				"repository_projects": "rp",
+				"repository_pre_receive_hooks": "rprh",
+				"secrets": "s",
+				"secret_scanning_alerts": "ssa",
+				"security_events": "se",
+				"single_file": "sf",
+				"statuses": "s",
+				"team_discussions": "td",
+				"vulnerability_alerts": "va",
+				"workflows": "w"
+			},
+			"created_at": ` + referenceTimeStr + `,
+			"updated_at": ` + referenceTimeStr + `,
+			"has_multiple_single_files": false,
+			"suspended_by": {
+				"login": "l",
+				"id": 1,
+				"avatar_url": "a",
+				"gravatar_id": "g",
+				"name": "n",
+				"company": "c",
+				"blog": "b",
+				"location": "l",
+				"email": "e",
+				"hireable": true,
+				"bio": "b",
+				"twitter_username": "t",
+				"public_repos": 1,
+				"followers": 1,
+				"following": 1,
+				"created_at": ` + referenceTimeStr + `,
+				"suspended_at": ` + referenceTimeStr + `,
+				"url": "u"
+			},
+			"suspended_at": ` + referenceTimeStr + `
+		}
+	}`
+
+	testJSONMarshal(t, u, want)
+}
+
+func TestPullRequestTargetEvent_Marshal(t *testing.T) {
+	testJSONMarshal(t, &PullRequestTargetEvent{}, "{}")
+
+	u := &PullRequestTargetEvent{
+		Action: String("a"),
+		Assignee: &User{
+			Login:     String("l"),
+			ID:        Int64(1),
+			NodeID:    String("n"),
+			URL:       String("u"),
+			ReposURL:  String("r"),
+			EventsURL: String("e"),
+			AvatarURL: String("a"),
+		},
+		Number:      Int(1),
+		PullRequest: &PullRequest{ID: Int64(1)},
+		Changes: &EditChange{
+			Title: &EditTitle{
+				From: String("TitleFrom"),
+			},
+			Body: &EditBody{
+				From: String("BodyFrom"),
+			},
+			Base: &EditBase{
+				Ref: &EditRef{
+					From: String("BaseRefFrom"),
+				},
+				SHA: &EditSHA{
+					From: String("BaseSHAFrom"),
+				},
+			},
+		},
+		RequestedReviewer: &User{
+			Login:     String("l"),
+			ID:        Int64(1),
+			NodeID:    String("n"),
+			URL:       String("u"),
+			ReposURL:  String("r"),
+			EventsURL: String("e"),
+			AvatarURL: String("a"),
 		},
+		RequestedTeam: &Team{ID: Int64(1)},
+		Label:         &Label{ID: Int64(1)},
+		Before:        String("before"),
+		After:         String("after"),
 		Repo: &Repository{
 			ID:   Int64(1),
 			URL:  String("s"),
 			Name: String("n"),
 		},
+		Organization: &Organization{
+			BillingEmail:                         String("be"),
+			Blog:                                 String("b"),
+			Company:                              String("c"),
+			Email:                                String("e"),
+			TwitterUsername:                      String("tu"),
+			Location:                             String("loc"),
+			Name:                                 String("n"),
+			Description:                          String("d"),
+			IsVerified:                           Bool(true),
+			HasOrganizationProjects:              Bool(true),
+			HasRepositoryProjects:                Bool(true),
+			DefaultRepoPermission:                String("drp"),
+			MembersCanCreateRepos:                Bool(true),
+			MembersCanCreateInternalRepos:        Bool(true),
+			MembersCanCreatePrivateRepos:         Bool(true),
+			MembersCanCreatePublicRepos:          Bool(false),
+			MembersAllowedRepositoryCreationType: String("marct"),
+			MembersCanCreatePages:                Bool(true),
+			MembersCanCreatePublicPages:          Bool(false),
+			MembersCanCreatePrivatePages:         Bool(true),
+		},
 		Sender: &User{
 			Login:     String("l"),
 			ID:        Int64(1),
@@ -14846,18 +15543,46 @@ func TestPullRequestReviewThreadEvent_Marshal(t *testing.T) {
 
 	want := `{
 		"action": "a",
+		"assignee": {
+			"login": "l",
+			"id": 1,
+			"node_id": "n",
+			"avatar_url": "a",
+			"url": "u",
+			"events_url": "e",
+			"repos_url": "r"
+		},
+		"number": 1,
 		"pull_request": {
 			"id": 1
 		},
-		"thread": {
-			"comments": [
-				{
-					"id": 1
+		"changes": {
+			"title": {
+				"from": "TitleFrom"
+			},
+			"body": {
+				"from": "BodyFrom"
+			},
+			"base": {
+				"ref": {
+					"from": "BaseRefFrom"
 				},
-				{
-					"id": 2
+				"sha": {
+					"from": "BaseSHAFrom"
 				}
-			]
+			}
+		},
+		"requested_reviewer": {
+			"login": "l",
+			"id": 1,
+			"node_id": "n",
+			"avatar_url": "a",
+			"url": "u",
+			"events_url": "e",
+			"repos_url": "r"
+		},
+		"requested_team": {
+			"id": 1
 		},
 		"repository": {
 			"id": 1,
@@ -14969,57 +15694,121 @@ func TestPullRequestReviewThreadEvent_Marshal(t *testing.T) {
 				"url": "u"
 			},
 			"suspended_at": ` + referenceTimeStr + `
-		}
+		},
+		"label": {
+			"id": 1
+		},
+		"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
+		},
+		"before": "before",
+		"after": "after"
 	}`
 
 	testJSONMarshal(t, u, want)
 }
 
-func TestPullRequestTargetEvent_Marshal(t *testing.T) {
-	testJSONMarshal(t, &PullRequestTargetEvent{}, "{}")
+func TestRepositoryVulnerabilityAlertEvent_Marshal(t *testing.T) {
+	testJSONMarshal(t, &RepositoryVulnerabilityAlertEvent{}, "{}")
 
-	u := &PullRequestTargetEvent{
+	u := &RepositoryVulnerabilityAlertEvent{
 		Action: String("a"),
-		Assignee: &User{
-			Login:     String("l"),
-			ID:        Int64(1),
-			NodeID:    String("n"),
-			URL:       String("u"),
-			ReposURL:  String("r"),
-			EventsURL: String("e"),
-			AvatarURL: String("a"),
-		},
-		Number:      Int(1),
-		PullRequest: &PullRequest{ID: Int64(1)},
-		Changes: &EditChange{
-			Title: &EditTitle{
-				From: String("TitleFrom"),
-			},
-			Body: &EditBody{
-				From: String("BodyFrom"),
+		Alert: &RepositoryVulnerabilityAlert{
+			ID:                  Int64(1),
+			AffectedRange:       String("ar"),
+			AffectedPackageName: String("apn"),
+			ExternalReference:   String("er"),
+			ExternalIdentifier:  String("ei"),
+			FixedIn:             String("fi"),
+			Dismisser: &User{
+				Login:     String("l"),
+				ID:        Int64(1),
+				NodeID:    String("n"),
+				URL:       String("u"),
+				ReposURL:  String("r"),
+				EventsURL: String("e"),
+				AvatarURL: String("a"),
 			},
-			Base: &EditBase{
-				Ref: &EditRef{
-					From: String("BaseRefFrom"),
-				},
-				SHA: &EditSHA{
-					From: String("BaseSHAFrom"),
-				},
+			DismissReason: String("dr"),
+			DismissedAt:   &Timestamp{referenceTime},
+		},
+		Repository: &Repository{
+			ID:   Int64(1),
+			URL:  String("s"),
+			Name: String("n"),
+		},
+	}
+
+	want := `{
+		"action": "a",
+		"alert": {
+			"id": 1,
+			"affected_range": "ar",
+			"affected_package_name": "apn",
+			"external_reference": "er",
+			"external_identifier": "ei",
+			"fixed_in": "fi",
+			"dismisser": {
+				"login": "l",
+				"id": 1,
+				"node_id": "n",
+				"avatar_url": "a",
+				"url": "u",
+				"events_url": "e",
+				"repos_url": "r"
 			},
+			"dismiss_reason": "dr",
+			"dismissed_at": ` + referenceTimeStr + `
 		},
-		RequestedReviewer: &User{
-			Login:     String("l"),
-			ID:        Int64(1),
-			NodeID:    String("n"),
-			URL:       String("u"),
-			ReposURL:  String("r"),
-			EventsURL: String("e"),
-			AvatarURL: String("a"),
+		"repository": {
+			"id": 1,
+			"name": "n",
+			"url": "s"
+		}
+	}`
+
+	testJSONMarshal(t, u, want)
+}
+
+func TestSecretScanningAlertEvent_Marshal(t *testing.T) {
+	testJSONMarshal(t, &SecretScanningAlertEvent{}, "{}")
+
+	u := &SecretScanningAlertEvent{
+		Action: String("a"),
+		Alert: &SecretScanningAlert{
+			Number:     Int(1),
+			SecretType: String("t"),
+			Resolution: String("r"),
+			ResolvedBy: &User{
+				Login:     String("l"),
+				ID:        Int64(1),
+				NodeID:    String("n"),
+				URL:       String("u"),
+				ReposURL:  String("r"),
+				EventsURL: String("e"),
+				AvatarURL: String("a"),
+			},
+			ResolvedAt: &Timestamp{referenceTime},
 		},
-		RequestedTeam: &Team{ID: Int64(1)},
-		Label:         &Label{ID: Int64(1)},
-		Before:        String("before"),
-		After:         String("after"),
 		Repo: &Repository{
 			ID:   Int64(1),
 			URL:  String("s"),
@@ -15047,6 +15836,18 @@ func TestPullRequestTargetEvent_Marshal(t *testing.T) {
 			MembersCanCreatePublicPages:          Bool(false),
 			MembersCanCreatePrivatePages:         Bool(true),
 		},
+		Enterprise: &Enterprise{
+			ID:          Int(1),
+			Slug:        String("s"),
+			Name:        String("n"),
+			NodeID:      String("nid"),
+			AvatarURL:   String("au"),
+			Description: String("d"),
+			WebsiteURL:  String("wu"),
+			HTMLURL:     String("hu"),
+			CreatedAt:   &Timestamp{referenceTime},
+			UpdatedAt:   &Timestamp{referenceTime},
+		},
 		Sender: &User{
 			Login:     String("l"),
 			ID:        Int64(1),
@@ -15153,51 +15954,59 @@ func TestPullRequestTargetEvent_Marshal(t *testing.T) {
 
 	want := `{
 		"action": "a",
-		"assignee": {
-			"login": "l",
-			"id": 1,
-			"node_id": "n",
-			"avatar_url": "a",
-			"url": "u",
-			"events_url": "e",
-			"repos_url": "r"
-		},
-		"number": 1,
-		"pull_request": {
-			"id": 1
-		},
-		"changes": {
-			"title": {
-				"from": "TitleFrom"
-			},
-			"body": {
-				"from": "BodyFrom"
+		"alert": {
+			"number": 1,
+			"secret_type": "t",
+			"resolution": "r",
+			"resolved_by": {
+				"login": "l",
+				"id": 1,
+				"node_id": "n",
+				"avatar_url": "a",
+				"url": "u",
+				"events_url": "e",
+				"repos_url": "r"
 			},
-			"base": {
-				"ref": {
-					"from": "BaseRefFrom"
-				},
-				"sha": {
-					"from": "BaseSHAFrom"
-				}
-			}
+			"resolved_at": ` + referenceTimeStr + `
 		},
-		"requested_reviewer": {
-			"login": "l",
+		"repository": {
 			"id": 1,
-			"node_id": "n",
-			"avatar_url": "a",
-			"url": "u",
-			"events_url": "e",
-			"repos_url": "r"
+			"name": "n",
+			"url": "s"
 		},
-		"requested_team": {
-			"id": 1
+        "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
 		},
-		"repository": {
+        "enterprise": {
 			"id": 1,
+			"slug": "s",
 			"name": "n",
-			"url": "s"
+			"node_id": "nid",
+			"avatar_url": "au",
+			"description": "d",
+			"website_url": "wu",
+			"html_url": "hu",
+			"created_at": ` + referenceTimeStr + `,
+			"updated_at": ` + referenceTimeStr + `
 		},
 		"sender": {
 			"login": "l",
@@ -15208,7 +16017,7 @@ func TestPullRequestTargetEvent_Marshal(t *testing.T) {
 			"events_url": "e",
 			"repos_url": "r"
 		},
-		"installation": {
+        "installation": {
 			"id": 1,
 			"node_id": "nid",
 			"app_id": 1,
@@ -15304,147 +16113,112 @@ func TestPullRequestTargetEvent_Marshal(t *testing.T) {
 				"url": "u"
 			},
 			"suspended_at": ` + referenceTimeStr + `
-		},
-		"label": {
-			"id": 1
-		},
-		"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
-		},
-		"before": "before",
-		"after": "after"
+		}
 	}`
 
 	testJSONMarshal(t, u, want)
 }
 
-func TestRepositoryVulnerabilityAlertEvent_Marshal(t *testing.T) {
-	testJSONMarshal(t, &RepositoryVulnerabilityAlertEvent{}, "{}")
-
-	u := &RepositoryVulnerabilityAlertEvent{
-		Action: String("a"),
-		Alert: &RepositoryVulnerabilityAlert{
-			ID:                  Int64(1),
-			AffectedRange:       String("ar"),
-			AffectedPackageName: String("apn"),
-			ExternalReference:   String("er"),
-			ExternalIdentifier:  String("ei"),
-			FixedIn:             String("fi"),
-			Dismisser: &User{
-				Login:     String("l"),
-				ID:        Int64(1),
-				NodeID:    String("n"),
-				URL:       String("u"),
-				ReposURL:  String("r"),
-				EventsURL: String("e"),
-				AvatarURL: String("a"),
+func TestSecurityAdvisoryEvent_Marshal(t *testing.T) {
+	testJSONMarshal(t, &SecurityAdvisoryEvent{}, "{}")
+	u := &SecurityAdvisoryEvent{
+		Action: String("published"),
+		SecurityAdvisory: &SecurityAdvisory{
+			GHSAID:      String("GHSA-rf4j-j272-some"),
+			Summary:     String("Siuuuuuuuuu"),
+			Description: String("desc"),
+			Severity:    String("moderate"),
+			Identifiers: []*AdvisoryIdentifier{
+				{
+					Value: String("GHSA-rf4j-j272-some"),
+					Type:  String("GHSA"),
+				},
+			},
+			References: []*AdvisoryReference{
+				{
+					URL: String("https://some-url"),
+				},
+			},
+			PublishedAt: &Timestamp{referenceTime},
+			UpdatedAt:   &Timestamp{referenceTime},
+			WithdrawnAt: nil,
+			Vulnerabilities: []*AdvisoryVulnerability{
+				{
+					Package: &VulnerabilityPackage{
+						Ecosystem: String("ucl"),
+						Name:      String("penaldo"),
+					},
+					Severity:               String("moderate"),
+					VulnerableVersionRange: String(">= 2.0.0, < 2.0.2"),
+					FirstPatchedVersion: &FirstPatchedVersion{
+						Identifier: String("2.0.2"),
+					},
+				},
 			},
-			DismissReason: String("dr"),
-			DismissedAt:   &Timestamp{referenceTime},
-		},
-		Repository: &Repository{
-			ID:   Int64(1),
-			URL:  String("s"),
-			Name: String("n"),
 		},
 	}
 
 	want := `{
-		"action": "a",
-		"alert": {
-			"id": 1,
-			"affected_range": "ar",
-			"affected_package_name": "apn",
-			"external_reference": "er",
-			"external_identifier": "ei",
-			"fixed_in": "fi",
-			"dismisser": {
-				"login": "l",
-				"id": 1,
-				"node_id": "n",
-				"avatar_url": "a",
-				"url": "u",
-				"events_url": "e",
-				"repos_url": "r"
-			},
-			"dismiss_reason": "dr",
-			"dismissed_at": ` + referenceTimeStr + `
-		},
-		"repository": {
-			"id": 1,
-			"name": "n",
-			"url": "s"
+		"action": "published",
+		"security_advisory": {
+		  "ghsa_id": "GHSA-rf4j-j272-some",
+		  "summary": "Siuuuuuuuuu",
+		  "description": "desc",
+		  "severity": "moderate",
+		  "identifiers": [
+			{
+			  "value": "GHSA-rf4j-j272-some",
+			  "type": "GHSA"
+			}
+		  ],
+		  "references": [
+			{
+			  "url": "https://some-url"
+			}
+		  ],
+		  "published_at": ` + referenceTimeStr + `,
+		  "updated_at": ` + referenceTimeStr + `,
+		  "withdrawn_at": null,
+		  "vulnerabilities": [
+			{
+			  "package": {
+				"ecosystem": "ucl",
+				"name": "penaldo"
+			  },
+			  "severity": "moderate",
+			  "vulnerable_version_range": ">= 2.0.0, < 2.0.2",
+			  "first_patched_version": {
+				"identifier": "2.0.2"
+			  }
+			}
+		  ]
 		}
-	}`
+	  }`
 
 	testJSONMarshal(t, u, want)
 }
 
-func TestSecretScanningAlertEvent_Marshal(t *testing.T) {
-	testJSONMarshal(t, &SecretScanningAlertEvent{}, "{}")
+func TestSecurityAndAnalysisEvent_Marshal(t *testing.T) {
+	testJSONMarshal(t, &SecurityAndAnalysisEvent{}, "{}")
 
-	u := &SecretScanningAlertEvent{
-		Action: String("a"),
-		Alert: &SecretScanningAlert{
-			Number:     Int(1),
-			SecretType: String("t"),
-			Resolution: String("r"),
-			ResolvedBy: &User{
-				Login:     String("l"),
-				ID:        Int64(1),
-				NodeID:    String("n"),
-				URL:       String("u"),
-				ReposURL:  String("r"),
-				EventsURL: String("e"),
-				AvatarURL: String("a"),
+	u := &SecurityAndAnalysisEvent{
+		Changes: &SecurityAndAnalysisChange{
+			From: &SecurityAndAnalysisChangeFrom{
+				SecurityAndAnalysis: &SecurityAndAnalysis{
+					AdvancedSecurity: &AdvancedSecurity{
+						Status: String("enabled"),
+					},
+					SecretScanning: &SecretScanning{
+						Status: String("enabled"),
+					},
+					SecretScanningPushProtection: &SecretScanningPushProtection{
+						Status: String("enabled"),
+					},
+					DependabotSecurityUpdates: &DependabotSecurityUpdates{
+						Status: String("enabled"),
+					},
+				},
 			},
-			ResolvedAt: &Timestamp{referenceTime},
-		},
-		Repo: &Repository{
-			ID:   Int64(1),
-			URL:  String("s"),
-			Name: String("n"),
-		},
-		Organization: &Organization{
-			BillingEmail:                         String("be"),
-			Blog:                                 String("b"),
-			Company:                              String("c"),
-			Email:                                String("e"),
-			TwitterUsername:                      String("tu"),
-			Location:                             String("loc"),
-			Name:                                 String("n"),
-			Description:                          String("d"),
-			IsVerified:                           Bool(true),
-			HasOrganizationProjects:              Bool(true),
-			HasRepositoryProjects:                Bool(true),
-			DefaultRepoPermission:                String("drp"),
-			MembersCanCreateRepos:                Bool(true),
-			MembersCanCreateInternalRepos:        Bool(true),
-			MembersCanCreatePrivateRepos:         Bool(true),
-			MembersCanCreatePublicRepos:          Bool(false),
-			MembersAllowedRepositoryCreationType: String("marct"),
-			MembersCanCreatePages:                Bool(true),
-			MembersCanCreatePublicPages:          Bool(false),
-			MembersCanCreatePrivatePages:         Bool(true),
 		},
 		Enterprise: &Enterprise{
 			ID:          Int(1),
@@ -15458,15 +16232,6 @@ func TestSecretScanningAlertEvent_Marshal(t *testing.T) {
 			CreatedAt:   &Timestamp{referenceTime},
 			UpdatedAt:   &Timestamp{referenceTime},
 		},
-		Sender: &User{
-			Login:     String("l"),
-			ID:        Int64(1),
-			NodeID:    String("n"),
-			URL:       String("u"),
-			ReposURL:  String("r"),
-			EventsURL: String("e"),
-			AvatarURL: String("a"),
-		},
 		Installation: &Installation{
 			ID:       Int64(1),
 			NodeID:   String("nid"),
@@ -15560,53 +16325,64 @@ func TestSecretScanningAlertEvent_Marshal(t *testing.T) {
 			},
 			SuspendedAt: &Timestamp{referenceTime},
 		},
+		Organization: &Organization{
+			BillingEmail:                         String("be"),
+			Blog:                                 String("b"),
+			Company:                              String("c"),
+			Email:                                String("e"),
+			TwitterUsername:                      String("tu"),
+			Location:                             String("loc"),
+			Name:                                 String("n"),
+			Description:                          String("d"),
+			IsVerified:                           Bool(true),
+			HasOrganizationProjects:              Bool(true),
+			HasRepositoryProjects:                Bool(true),
+			DefaultRepoPermission:                String("drp"),
+			MembersCanCreateRepos:                Bool(true),
+			MembersCanCreateInternalRepos:        Bool(true),
+			MembersCanCreatePrivateRepos:         Bool(true),
+			MembersCanCreatePublicRepos:          Bool(false),
+			MembersAllowedRepositoryCreationType: String("marct"),
+			MembersCanCreatePages:                Bool(true),
+			MembersCanCreatePublicPages:          Bool(false),
+			MembersCanCreatePrivatePages:         Bool(true),
+		},
+		Repository: &Repository{
+			ID:   Int64(1),
+			URL:  String("s"),
+			Name: String("n"),
+		},
+		Sender: &User{
+			Login:     String("l"),
+			ID:        Int64(1),
+			NodeID:    String("n"),
+			URL:       String("u"),
+			ReposURL:  String("r"),
+			EventsURL: String("e"),
+			AvatarURL: String("a"),
+		},
 	}
 
 	want := `{
-		"action": "a",
-		"alert": {
-			"number": 1,
-			"secret_type": "t",
-			"resolution": "r",
-			"resolved_by": {
-				"login": "l",
-				"id": 1,
-				"node_id": "n",
-				"avatar_url": "a",
-				"url": "u",
-				"events_url": "e",
-				"repos_url": "r"
-			},
-			"resolved_at": ` + referenceTimeStr + `
-		},
-		"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
+		"changes": {
+			"from": {
+				"security_and_analysis": {
+					"advanced_security": {
+						"status": "enabled"
+					},
+					"secret_scanning": {
+						"status": "enabled"
+					},
+					"secret_scanning_push_protection": {
+						"status": "enabled"
+					},
+					"dependabot_security_updates": {
+						"status": "enabled"
+					}
+				}
+			}
 		},
-        "enterprise": {
+		"enterprise": {
 			"id": 1,
 			"slug": "s",
 			"name": "n",
@@ -15618,16 +16394,7 @@ func TestSecretScanningAlertEvent_Marshal(t *testing.T) {
 			"created_at": ` + referenceTimeStr + `,
 			"updated_at": ` + referenceTimeStr + `
 		},
-		"sender": {
-			"login": "l",
-			"id": 1,
-			"node_id": "n",
-			"avatar_url": "a",
-			"url": "u",
-			"events_url": "e",
-			"repos_url": "r"
-		},
-        "installation": {
+		"installation": {
 			"id": 1,
 			"node_id": "nid",
 			"app_id": 1,
@@ -15723,87 +16490,45 @@ func TestSecretScanningAlertEvent_Marshal(t *testing.T) {
 				"url": "u"
 			},
 			"suspended_at": ` + referenceTimeStr + `
-		}
-	}`
-
-	testJSONMarshal(t, u, want)
-}
-
-func TestSecurityAdvisoryEvent_Marshal(t *testing.T) {
-	testJSONMarshal(t, &SecurityAdvisoryEvent{}, "{}")
-	u := &SecurityAdvisoryEvent{
-		Action: String("published"),
-		SecurityAdvisory: &SecurityAdvisory{
-			GHSAID:      String("GHSA-rf4j-j272-some"),
-			Summary:     String("Siuuuuuuuuu"),
-			Description: String("desc"),
-			Severity:    String("moderate"),
-			Identifiers: []*AdvisoryIdentifier{
-				{
-					Value: String("GHSA-rf4j-j272-some"),
-					Type:  String("GHSA"),
-				},
-			},
-			References: []*AdvisoryReference{
-				{
-					URL: String("https://some-url"),
-				},
-			},
-			PublishedAt: &Timestamp{referenceTime},
-			UpdatedAt:   &Timestamp{referenceTime},
-			WithdrawnAt: nil,
-			Vulnerabilities: []*AdvisoryVulnerability{
-				{
-					Package: &VulnerabilityPackage{
-						Ecosystem: String("ucl"),
-						Name:      String("penaldo"),
-					},
-					Severity:               String("moderate"),
-					VulnerableVersionRange: String(">= 2.0.0, < 2.0.2"),
-					FirstPatchedVersion: &FirstPatchedVersion{
-						Identifier: String("2.0.2"),
-					},
-				},
-			},
 		},
-	}
-
-	want := `{
-		"action": "published",
-		"security_advisory": {
-		  "ghsa_id": "GHSA-rf4j-j272-some",
-		  "summary": "Siuuuuuuuuu",
-		  "description": "desc",
-		  "severity": "moderate",
-		  "identifiers": [
-			{
-			  "value": "GHSA-rf4j-j272-some",
-			  "type": "GHSA"
-			}
-		  ],
-		  "references": [
-			{
-			  "url": "https://some-url"
-			}
-		  ],
-		  "published_at": ` + referenceTimeStr + `,
-		  "updated_at": ` + referenceTimeStr + `,
-		  "withdrawn_at": null,
-		  "vulnerabilities": [
-			{
-			  "package": {
-				"ecosystem": "ucl",
-				"name": "penaldo"
-			  },
-			  "severity": "moderate",
-			  "vulnerable_version_range": ">= 2.0.0, < 2.0.2",
-			  "first_patched_version": {
-				"identifier": "2.0.2"
-			  }
-			}
-		  ]
-		}
-	  }`
+		"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
+		},
+		"repository": {
+			"id": 1,
+			"url": "s",
+			"name": "n"
+		},
+		"sender": {
+			"login": "l",
+			"id": 1,
+			"node_id": "n",
+			"avatar_url": "a",
+			"url": "u",
+			"events_url": "e",
+			"repos_url": "r"
+		},
+		"target_type": "running"
+	}`
 
 	testJSONMarshal(t, u, want)
 }
diff --git a/github/github-accessors_test.go b/github/github-accessors_test.go
index 712d8fc9..12d05f2d 100644
--- a/github/github-accessors_test.go
+++ b/github/github-accessors_test.go
@@ -996,6 +996,26 @@ func TestAppConfig_GetWebhookSecret(tt *testing.T) {
 	a.GetWebhookSecret()
 }
 
+func TestArchivedAt_GetFrom(tt *testing.T) {
+	var zeroValue Timestamp
+	a := &ArchivedAt{From: &zeroValue}
+	a.GetFrom()
+	a = &ArchivedAt{}
+	a.GetFrom()
+	a = nil
+	a.GetFrom()
+}
+
+func TestArchivedAt_GetTo(tt *testing.T) {
+	var zeroValue Timestamp
+	a := &ArchivedAt{To: &zeroValue}
+	a.GetTo()
+	a = &ArchivedAt{}
+	a.GetTo()
+	a = nil
+	a.GetTo()
+}
+
 func TestArtifact_GetArchiveDownloadURL(tt *testing.T) {
 	var zeroValue string
 	a := &Artifact{ArchiveDownloadURL: &zeroValue}
@@ -16804,6 +16824,314 @@ func TestProjectPermissionLevel_GetUser(tt *testing.T) {
 	p.GetUser()
 }
 
+func TestProjectsV2_GetClosedAt(tt *testing.T) {
+	var zeroValue Timestamp
+	p := &ProjectsV2{ClosedAt: &zeroValue}
+	p.GetClosedAt()
+	p = &ProjectsV2{}
+	p.GetClosedAt()
+	p = nil
+	p.GetClosedAt()
+}
+
+func TestProjectsV2_GetCreatedAt(tt *testing.T) {
+	var zeroValue Timestamp
+	p := &ProjectsV2{CreatedAt: &zeroValue}
+	p.GetCreatedAt()
+	p = &ProjectsV2{}
+	p.GetCreatedAt()
+	p = nil
+	p.GetCreatedAt()
+}
+
+func TestProjectsV2_GetCreator(tt *testing.T) {
+	p := &ProjectsV2{}
+	p.GetCreator()
+	p = nil
+	p.GetCreator()
+}
+
+func TestProjectsV2_GetDeletedAt(tt *testing.T) {
+	var zeroValue Timestamp
+	p := &ProjectsV2{DeletedAt: &zeroValue}
+	p.GetDeletedAt()
+	p = &ProjectsV2{}
+	p.GetDeletedAt()
+	p = nil
+	p.GetDeletedAt()
+}
+
+func TestProjectsV2_GetDeletedBy(tt *testing.T) {
+	p := &ProjectsV2{}
+	p.GetDeletedBy()
+	p = nil
+	p.GetDeletedBy()
+}
+
+func TestProjectsV2_GetDescription(tt *testing.T) {
+	var zeroValue string
+	p := &ProjectsV2{Description: &zeroValue}
+	p.GetDescription()
+	p = &ProjectsV2{}
+	p.GetDescription()
+	p = nil
+	p.GetDescription()
+}
+
+func TestProjectsV2_GetID(tt *testing.T) {
+	var zeroValue int64
+	p := &ProjectsV2{ID: &zeroValue}
+	p.GetID()
+	p = &ProjectsV2{}
+	p.GetID()
+	p = nil
+	p.GetID()
+}
+
+func TestProjectsV2_GetNodeID(tt *testing.T) {
+	var zeroValue string
+	p := &ProjectsV2{NodeID: &zeroValue}
+	p.GetNodeID()
+	p = &ProjectsV2{}
+	p.GetNodeID()
+	p = nil
+	p.GetNodeID()
+}
+
+func TestProjectsV2_GetNumber(tt *testing.T) {
+	var zeroValue int
+	p := &ProjectsV2{Number: &zeroValue}
+	p.GetNumber()
+	p = &ProjectsV2{}
+	p.GetNumber()
+	p = nil
+	p.GetNumber()
+}
+
+func TestProjectsV2_GetOwner(tt *testing.T) {
+	p := &ProjectsV2{}
+	p.GetOwner()
+	p = nil
+	p.GetOwner()
+}
+
+func TestProjectsV2_GetPublic(tt *testing.T) {
+	var zeroValue bool
+	p := &ProjectsV2{Public: &zeroValue}
+	p.GetPublic()
+	p = &ProjectsV2{}
+	p.GetPublic()
+	p = nil
+	p.GetPublic()
+}
+
+func TestProjectsV2_GetShortDescription(tt *testing.T) {
+	var zeroValue string
+	p := &ProjectsV2{ShortDescription: &zeroValue}
+	p.GetShortDescription()
+	p = &ProjectsV2{}
+	p.GetShortDescription()
+	p = nil
+	p.GetShortDescription()
+}
+
+func TestProjectsV2_GetTitle(tt *testing.T) {
+	var zeroValue string
+	p := &ProjectsV2{Title: &zeroValue}
+	p.GetTitle()
+	p = &ProjectsV2{}
+	p.GetTitle()
+	p = nil
+	p.GetTitle()
+}
+
+func TestProjectsV2_GetUpdatedAt(tt *testing.T) {
+	var zeroValue Timestamp
+	p := &ProjectsV2{UpdatedAt: &zeroValue}
+	p.GetUpdatedAt()
+	p = &ProjectsV2{}
+	p.GetUpdatedAt()
+	p = nil
+	p.GetUpdatedAt()
+}
+
+func TestProjectV2Event_GetAction(tt *testing.T) {
+	var zeroValue string
+	p := &ProjectV2Event{Action: &zeroValue}
+	p.GetAction()
+	p = &ProjectV2Event{}
+	p.GetAction()
+	p = nil
+	p.GetAction()
+}
+
+func TestProjectV2Event_GetInstallation(tt *testing.T) {
+	p := &ProjectV2Event{}
+	p.GetInstallation()
+	p = nil
+	p.GetInstallation()
+}
+
+func TestProjectV2Event_GetOrg(tt *testing.T) {
+	p := &ProjectV2Event{}
+	p.GetOrg()
+	p = nil
+	p.GetOrg()
+}
+
+func TestProjectV2Event_GetProjectsV2(tt *testing.T) {
+	p := &ProjectV2Event{}
+	p.GetProjectsV2()
+	p = nil
+	p.GetProjectsV2()
+}
+
+func TestProjectV2Event_GetSender(tt *testing.T) {
+	p := &ProjectV2Event{}
+	p.GetSender()
+	p = nil
+	p.GetSender()
+}
+
+func TestProjectV2Item_GetArchivedAt(tt *testing.T) {
+	var zeroValue Timestamp
+	p := &ProjectV2Item{ArchivedAt: &zeroValue}
+	p.GetArchivedAt()
+	p = &ProjectV2Item{}
+	p.GetArchivedAt()
+	p = nil
+	p.GetArchivedAt()
+}
+
+func TestProjectV2Item_GetContentNodeID(tt *testing.T) {
+	var zeroValue string
+	p := &ProjectV2Item{ContentNodeID: &zeroValue}
+	p.GetContentNodeID()
+	p = &ProjectV2Item{}
+	p.GetContentNodeID()
+	p = nil
+	p.GetContentNodeID()
+}
+
+func TestProjectV2Item_GetContentType(tt *testing.T) {
+	var zeroValue string
+	p := &ProjectV2Item{ContentType: &zeroValue}
+	p.GetContentType()
+	p = &ProjectV2Item{}
+	p.GetContentType()
+	p = nil
+	p.GetContentType()
+}
+
+func TestProjectV2Item_GetCreatedAt(tt *testing.T) {
+	var zeroValue Timestamp
+	p := &ProjectV2Item{CreatedAt: &zeroValue}
+	p.GetCreatedAt()
+	p = &ProjectV2Item{}
+	p.GetCreatedAt()
+	p = nil
+	p.GetCreatedAt()
+}
+
+func TestProjectV2Item_GetCreator(tt *testing.T) {
+	p := &ProjectV2Item{}
+	p.GetCreator()
+	p = nil
+	p.GetCreator()
+}
+
+func TestProjectV2Item_GetID(tt *testing.T) {
+	var zeroValue int64
+	p := &ProjectV2Item{ID: &zeroValue}
+	p.GetID()
+	p = &ProjectV2Item{}
+	p.GetID()
+	p = nil
+	p.GetID()
+}
+
+func TestProjectV2Item_GetNodeID(tt *testing.T) {
+	var zeroValue string
+	p := &ProjectV2Item{NodeID: &zeroValue}
+	p.GetNodeID()
+	p = &ProjectV2Item{}
+	p.GetNodeID()
+	p = nil
+	p.GetNodeID()
+}
+
+func TestProjectV2Item_GetProjectNodeID(tt *testing.T) {
+	var zeroValue string
+	p := &ProjectV2Item{ProjectNodeID: &zeroValue}
+	p.GetProjectNodeID()
+	p = &ProjectV2Item{}
+	p.GetProjectNodeID()
+	p = nil
+	p.GetProjectNodeID()
+}
+
+func TestProjectV2Item_GetUpdatedAt(tt *testing.T) {
+	var zeroValue Timestamp
+	p := &ProjectV2Item{UpdatedAt: &zeroValue}
+	p.GetUpdatedAt()
+	p = &ProjectV2Item{}
+	p.GetUpdatedAt()
+	p = nil
+	p.GetUpdatedAt()
+}
+
+func TestProjectV2ItemChange_GetArchivedAt(tt *testing.T) {
+	p := &ProjectV2ItemChange{}
+	p.GetArchivedAt()
+	p = nil
+	p.GetArchivedAt()
+}
+
+func TestProjectV2ItemEvent_GetAction(tt *testing.T) {
+	var zeroValue string
+	p := &ProjectV2ItemEvent{Action: &zeroValue}
+	p.GetAction()
+	p = &ProjectV2ItemEvent{}
+	p.GetAction()
+	p = nil
+	p.GetAction()
+}
+
+func TestProjectV2ItemEvent_GetChanges(tt *testing.T) {
+	p := &ProjectV2ItemEvent{}
+	p.GetChanges()
+	p = nil
+	p.GetChanges()
+}
+
+func TestProjectV2ItemEvent_GetInstallation(tt *testing.T) {
+	p := &ProjectV2ItemEvent{}
+	p.GetInstallation()
+	p = nil
+	p.GetInstallation()
+}
+
+func TestProjectV2ItemEvent_GetOrg(tt *testing.T) {
+	p := &ProjectV2ItemEvent{}
+	p.GetOrg()
+	p = nil
+	p.GetOrg()
+}
+
+func TestProjectV2ItemEvent_GetProjectV2Item(tt *testing.T) {
+	p := &ProjectV2ItemEvent{}
+	p.GetProjectV2Item()
+	p = nil
+	p.GetProjectV2Item()
+}
+
+func TestProjectV2ItemEvent_GetSender(tt *testing.T) {
+	p := &ProjectV2ItemEvent{}
+	p.GetSender()
+	p = nil
+	p.GetSender()
+}
+
 func TestProtection_GetAllowDeletions(tt *testing.T) {
 	p := &Protection{}
 	p.GetAllowDeletions()
@@ -23643,6 +23971,62 @@ func TestSecurityAndAnalysis_GetSecretScanningPushProtection(tt *testing.T) {
 	s.GetSecretScanningPushProtection()
 }
 
+func TestSecurityAndAnalysisChange_GetFrom(tt *testing.T) {
+	s := &SecurityAndAnalysisChange{}
+	s.GetFrom()
+	s = nil
+	s.GetFrom()
+}
+
+func TestSecurityAndAnalysisChangeFrom_GetSecurityAndAnalysis(tt *testing.T) {
+	s := &SecurityAndAnalysisChangeFrom{}
+	s.GetSecurityAndAnalysis()
+	s = nil
+	s.GetSecurityAndAnalysis()
+}
+
+func TestSecurityAndAnalysisEvent_GetChanges(tt *testing.T) {
+	s := &SecurityAndAnalysisEvent{}
+	s.GetChanges()
+	s = nil
+	s.GetChanges()
+}
+
+func TestSecurityAndAnalysisEvent_GetEnterprise(tt *testing.T) {
+	s := &SecurityAndAnalysisEvent{}
+	s.GetEnterprise()
+	s = nil
+	s.GetEnterprise()
+}
+
+func TestSecurityAndAnalysisEvent_GetInstallation(tt *testing.T) {
+	s := &SecurityAndAnalysisEvent{}
+	s.GetInstallation()
+	s = nil
+	s.GetInstallation()
+}
+
+func TestSecurityAndAnalysisEvent_GetOrganization(tt *testing.T) {
+	s := &SecurityAndAnalysisEvent{}
+	s.GetOrganization()
+	s = nil
+	s.GetOrganization()
+}
+
+func TestSecurityAndAnalysisEvent_GetRepository(tt *testing.T) {
+	s := &SecurityAndAnalysisEvent{}
+	s.GetRepository()
+	s = nil
+	s.GetRepository()
+}
+
+func TestSecurityAndAnalysisEvent_GetSender(tt *testing.T) {
+	s := &SecurityAndAnalysisEvent{}
+	s.GetSender()
+	s = nil
+	s.GetSender()
+}
+
 func TestSelectedReposList_GetTotalCount(tt *testing.T) {
 	var zeroValue int
 	s := &SelectedReposList{TotalCount: &zeroValue}
diff --git a/github/messages_test.go b/github/messages_test.go
index 8ee38eb3..91a25027 100644
--- a/github/messages_test.go
+++ b/github/messages_test.go
@@ -404,6 +404,14 @@ func TestParseWebHook(t *testing.T) {
 			payload:     &ProjectColumnEvent{},
 			messageType: "project_column",
 		},
+		{
+			payload:     &ProjectV2Event{},
+			messageType: "projects_v2",
+		},
+		{
+			payload:     &ProjectV2ItemEvent{},
+			messageType: "projects_v2_item",
+		},
 		{
 			payload:     &PublicEvent{},
 			messageType: "public",
@@ -452,6 +460,10 @@ func TestParseWebHook(t *testing.T) {
 			payload:     &SecurityAdvisoryEvent{},
 			messageType: "security_advisory",
 		},
+		{
+			payload:     &SecurityAndAnalysisEvent{},
+			messageType: "security_and_analysis",
+		},
 		{
 			payload:     &StarEvent{},
 			messageType: "star",
diff --git a/github/repos_hooks_deliveries_test.go b/github/repos_hooks_deliveries_test.go
index d1dda365..d5e1a383 100644
--- a/github/repos_hooks_deliveries_test.go
+++ b/github/repos_hooks_deliveries_test.go
@@ -176,6 +176,8 @@ var hookDeliveryPayloadTypeToStruct = map[string]interface{}{
 	"project":                        &ProjectEvent{},
 	"project_card":                   &ProjectCardEvent{},
 	"project_column":                 &ProjectColumnEvent{},
+	"projects_v2":                    &ProjectV2Event{},
+	"projects_v2_item":               &ProjectV2ItemEvent{},
 	"public":                         &PublicEvent{},
 	"pull_request":                   &PullRequestEvent{},
 	"pull_request_review":            &PullRequestReviewEvent{},
@@ -190,6 +192,7 @@ var hookDeliveryPayloadTypeToStruct = map[string]interface{}{
 	"repository_vulnerability_alert": &RepositoryVulnerabilityAlertEvent{},
 	"secret_scanning_alert":          &SecretScanningAlertEvent{},
 	"security_advisory":              &SecurityAdvisoryEvent{},
+	"security_and_analysis":          &SecurityAndAnalysisEvent{},
 	"star":                           &StarEvent{},
 	"status":                         &StatusEvent{},
 	"team":                           &TeamEvent{},
diff --git a/github/security_advisories_test.go b/github/security_advisories_test.go
new file mode 100644
index 00000000..e4a6fbd7
--- /dev/null
+++ b/github/security_advisories_test.go
@@ -0,0 +1,52 @@
+// Copyright 2023 The go-github AUTHORS. All rights reserved.
+//
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package github
+
+import (
+	"context"
+	"net/http"
+	"testing"
+)
+
+func TestSecurityAdvisoriesService_RequestCVE(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/repos/o/r/security-advisories/ghsa_id_ok/cve", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "POST")
+		w.WriteHeader(http.StatusOK)
+	})
+
+	mux.HandleFunc("/repos/o/r/security-advisories/ghsa_id_accepted/cve", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "POST")
+		w.WriteHeader(http.StatusAccepted)
+	})
+
+	ctx := context.Background()
+	_, err := client.SecurityAdvisories.RequestCVE(ctx, "o", "r", "ghsa_id_ok")
+	if err != nil {
+		t.Errorf("SecurityAdvisoriesService.RequestCVE returned error: %v", err)
+	}
+
+	_, err = client.SecurityAdvisories.RequestCVE(ctx, "o", "r", "ghsa_id_accepted")
+	if err != nil {
+		t.Errorf("SecurityAdvisoriesService.RequestCVE returned error: %v", err)
+	}
+
+	const methodName = "RequestCVE"
+	testBadOptions(t, methodName, func() (err error) {
+		_, err = client.SecurityAdvisories.RequestCVE(ctx, "\n", "\n", "\n")
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		resp, err := client.SecurityAdvisories.RequestCVE(ctx, "o", "r", "ghsa_id")
+		if err == nil {
+			t.Errorf("testNewRequestAndDoFailure %v should have return err", methodName)
+		}
+		return resp, err
+	})
+}