Repository: xanzy/go-gitlab
Pull request #1913 (2024-04-11 14:05:55)

New events webhooks
Hi,

I'm adding support for new events webhooks:
- Resource Access Token events project and group webhook: https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#project-and-group-access-token-events
- Member Events group webhook: https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#group-member-events

Thanks.


Patch:
diff --git a/draft_notes.go b/draft_notes.go
deleted file mode 100644
index 376e4d0..0000000
--- a/draft_notes.go
+++ /dev/null
@@ -1,233 +0,0 @@
-//
-// Copyright 2021, Sander van Harmelen
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-package gitlab
-
-import (
-	"fmt"
-	"net/http"
-)
-
-type DraftNote struct {
-	ID                int           `json:"id"`
-	AuthorID          int           `json:"author_id"`
-	MergeRequestID    int           `json:"merge_request_id"`
-	ResolveDiscussion bool          `json:"resolve_discussion"`
-	DiscussionID      string        `json:"discussion_id"`
-	Note              string        `json:"note"`
-	CommitID          string        `json:"commit_id"`
-	LineCode          string        `json:"line_code"`
-	Position          *NotePosition `json:"position"`
-}
-
-// DraftNotesService handles communication with the draft notes related methods
-// of the GitLab API.
-//
-// GitLab API docs:
-// https://docs.gitlab.com/ee/api/draft_notes.html#list-all-merge-request-draft-notes
-type DraftNotesService struct {
-	client *Client
-}
-
-// ListDraftNotesOptions represents the available ListDraftNotes()
-// options.
-//
-// GitLab API docs:
-// https://docs.gitlab.com/ee/api/draft_notes.html#list-all-merge-request-draft-notes
-type ListDraftNotesOptions struct {
-	ListOptions
-	OrderBy *string `url:"order_by,omitempty" json:"order_by,omitempty"`
-	Sort    *string `url:"sort,omitempty" json:"sort,omitempty"`
-}
-
-// ListDraftNotes gets a list of all draft notes for a merge request.
-//
-// Gitlab API docs:
-// https://docs.gitlab.com/ee/api/draft_notes.html#list-all-merge-request-draft-notes
-func (s *DraftNotesService) ListDraftNotes(pid interface{}, mergeRequest int, opt *ListDraftNotesOptions, options ...RequestOptionFunc) ([]*DraftNote, *Response, error) {
-	project, err := parseID(pid)
-	if err != nil {
-		return nil, nil, err
-	}
-	u := fmt.Sprintf("projects/%s/merge_requests/%d/draft_notes", PathEscape(project), mergeRequest)
-
-	req, err := s.client.NewRequest(http.MethodGet, u, opt, options)
-	if err != nil {
-		return nil, nil, err
-	}
-
-	var n []*DraftNote
-	resp, err := s.client.Do(req, &n)
-	if err != nil {
-		return nil, resp, err
-	}
-
-	return n, resp, nil
-}
-
-// GetDraftNote gets a single draft note for a merge request.
-//
-// Gitlab API docs:
-// https://docs.gitlab.com/ee/api/draft_notes.html#get-a-single-draft-note
-func (s *DraftNotesService) GetDraftNote(pid interface{}, mergeRequest int, note int, options ...RequestOptionFunc) (*DraftNote, *Response, error) {
-	project, err := parseID(pid)
-	if err != nil {
-		return nil, nil, err
-	}
-	u := fmt.Sprintf("projects/%s/merge_requests/%d/draft_notes/%d", PathEscape(project), mergeRequest, note)
-
-	req, err := s.client.NewRequest(http.MethodGet, u, nil, options)
-	if err != nil {
-		return nil, nil, err
-	}
-
-	n := new(DraftNote)
-	resp, err := s.client.Do(req, &n)
-	if err != nil {
-		return nil, resp, err
-	}
-
-	return n, resp, nil
-}
-
-// CreateDraftNoteOptions represents the available CreateDraftNote()
-// options.
-//
-// Gitlab API docs:
-// https://docs.gitlab.com/ee/api/draft_notes.html#create-a-draft-note
-type CreateDraftNoteOptions struct {
-	Note                  *string          `url:"note" json:"note"`
-	CommitID              *string          `url:"commit_id,omitempty" json:"commit_id,omitempty"`
-	InReplyToDiscussionID *string          `url:"in_reply_to_discussion_id,omitempty" json:"in_reply_to_discussion_id,omitempty"`
-	ResolveDiscussion     *bool            `url:"resolve_discussion,omitempty" json:"resolve_discussion,omitempty"`
-	Position              *PositionOptions `url:"position,omitempty" json:"position,omitempty"`
-}
-
-// CreateDraftNote creates a draft note for a merge request.
-//
-// Gitlab API docs:
-// https://docs.gitlab.com/ee/api/draft_notes.html#create-a-draft-note
-func (s *DraftNotesService) CreateDraftNote(pid interface{}, mergeRequest int, opt *CreateDraftNoteOptions, options ...RequestOptionFunc) (*DraftNote, *Response, error) {
-	project, err := parseID(pid)
-	if err != nil {
-		return nil, nil, err
-	}
-	u := fmt.Sprintf("projects/%s/merge_requests/%d/draft_notes", PathEscape(project), mergeRequest)
-
-	req, err := s.client.NewRequest(http.MethodPost, u, opt, options)
-	if err != nil {
-		return nil, nil, err
-	}
-
-	n := new(DraftNote)
-	resp, err := s.client.Do(req, &n)
-	if err != nil {
-		return nil, resp, err
-	}
-
-	return n, resp, nil
-}
-
-// UpdateDraftNoteOptions represents the available UpdateDraftNote()
-// options.
-//
-// Gitlab API docs:
-// https://docs.gitlab.com/ee/api/draft_notes.html#create-a-draft-note
-type UpdateDraftNoteOptions struct {
-	Note     *string          `url:"note,omitempty" json:"note,omitempty"`
-	Position *PositionOptions `url:"position,omitempty" json:"position,omitempty"`
-}
-
-// UpdateDraftNote updates a draft note for a merge request.
-//
-// Gitlab API docs: https://docs.gitlab.com/ee/api/draft_notes.html#create-a-draft-note
-func (s *DraftNotesService) UpdateDraftNote(pid interface{}, mergeRequest int, note int, opt *UpdateDraftNoteOptions, options ...RequestOptionFunc) (*DraftNote, *Response, error) {
-	project, err := parseID(pid)
-	if err != nil {
-		return nil, nil, err
-	}
-	u := fmt.Sprintf("projects/%s/merge_requests/%d/draft_notes/%d", PathEscape(project), mergeRequest, note)
-
-	req, err := s.client.NewRequest(http.MethodPut, u, opt, options)
-	if err != nil {
-		return nil, nil, err
-	}
-
-	n := new(DraftNote)
-	resp, err := s.client.Do(req, &n)
-	if err != nil {
-		return nil, resp, err
-	}
-
-	return n, resp, nil
-}
-
-// DeleteDraftNote deletes a single draft note for a merge request.
-//
-// Gitlab API docs:
-// https://docs.gitlab.com/ee/api/draft_notes.html#delete-a-draft-note
-func (s *DraftNotesService) DeleteDraftNote(pid interface{}, mergeRequest int, note int, options ...RequestOptionFunc) (*Response, error) {
-	project, err := parseID(pid)
-	if err != nil {
-		return nil, err
-	}
-	u := fmt.Sprintf("projects/%s/merge_requests/%d/draft_notes/%d", PathEscape(project), mergeRequest, note)
-
-	req, err := s.client.NewRequest(http.MethodDelete, u, nil, options)
-	if err != nil {
-		return nil, err
-	}
-
-	return s.client.Do(req, nil)
-}
-
-// PublishDraftNote publishes a single draft note for a merge request.
-//
-// Gitlab API docs:
-// https://docs.gitlab.com/ee/api/draft_notes.html#publish-a-draft-note
-func (s *DraftNotesService) PublishDraftNote(pid interface{}, mergeRequest int, note int, options ...RequestOptionFunc) (*Response, error) {
-	project, err := parseID(pid)
-	if err != nil {
-		return nil, err
-	}
-	u := fmt.Sprintf("projects/%s/merge_requests/%d/draft_notes/%d/publish", PathEscape(project), mergeRequest, note)
-
-	req, err := s.client.NewRequest(http.MethodPut, u, nil, options)
-	if err != nil {
-		return nil, err
-	}
-
-	return s.client.Do(req, nil)
-}
-
-// PublishAllDraftNotes publishes all draft notes for a merge request that belong to the user.
-//
-// Gitlab API docs:
-// https://docs.gitlab.com/ee/api/draft_notes.html#publish-a-draft-note
-func (s *DraftNotesService) PublishAllDraftNotes(pid interface{}, mergeRequest int, options ...RequestOptionFunc) (*Response, error) {
-	project, err := parseID(pid)
-	if err != nil {
-		return nil, err
-	}
-	u := fmt.Sprintf("projects/%s/merge_requests/%d/draft_notes/bulk_publish", PathEscape(project), mergeRequest)
-
-	req, err := s.client.NewRequest(http.MethodPost, u, nil, options)
-	if err != nil {
-		return nil, err
-	}
-
-	return s.client.Do(req, nil)
-}
diff --git a/event_webhook_types.go b/event_webhook_types.go
index 01b0983..fa1fe5c 100644
--- a/event_webhook_types.go
+++ b/event_webhook_types.go
@@ -512,7 +512,7 @@ type MergeCommentEvent struct {
 		System           bool          `json:"system"`
 		Type             string        `json:"type"`
 		UpdatedAt        string        `json:"updated_at"`
-		UpdatedByID      int           `json:"updated_by_id"`
+		UpdatedByID      string        `json:"updated_by_id"`
 		Description      string        `json:"description"`
 		URL              string        `json:"url"`
 	} `json:"object_attributes"`
diff --git a/gitlab.go b/gitlab.go
index e492050..c773ef5 100644
--- a/gitlab.go
+++ b/gitlab.go
@@ -124,7 +124,6 @@ type Client struct {
 	Deployments                  *DeploymentsService
 	Discussions                  *DiscussionsService
 	DockerfileTemplate           *DockerfileTemplatesService
-	DraftNotes                   *DraftNotesService
 	Environments                 *EnvironmentsService
 	EpicIssues                   *EpicIssuesService
 	Epics                        *EpicsService
@@ -358,7 +357,6 @@ func newClient(options ...ClientOptionFunc) (*Client, error) {
 	c.Deployments = &DeploymentsService{client: c}
 	c.Discussions = &DiscussionsService{client: c}
 	c.DockerfileTemplate = &DockerfileTemplatesService{client: c}
-	c.DraftNotes = &DraftNotesService{client: c}
 	c.Environments = &EnvironmentsService{client: c}
 	c.EpicIssues = &EpicIssuesService{client: c}
 	c.Epics = &EpicsService{client: c}
diff --git a/group_hooks.go b/group_hooks.go
index 56f2fae..09e812a 100644
--- a/group_hooks.go
+++ b/group_hooks.go
@@ -26,27 +26,29 @@ import (
 //
 // GitLab API docs: https://docs.gitlab.com/ee/api/groups.html#list-group-hooks
 type GroupHook struct {
-	ID                       int        `json:"id"`
-	URL                      string     `json:"url"`
-	GroupID                  int        `json:"group_id"`
-	PushEvents               bool       `json:"push_events"`
-	PushEventsBranchFilter   string     `json:"push_events_branch_filter"`
-	IssuesEvents             bool       `json:"issues_events"`
-	ConfidentialIssuesEvents bool       `json:"confidential_issues_events"`
-	ConfidentialNoteEvents   bool       `json:"confidential_note_events"`
-	MergeRequestsEvents      bool       `json:"merge_requests_events"`
-	TagPushEvents            bool       `json:"tag_push_events"`
-	NoteEvents               bool       `json:"note_events"`
-	JobEvents                bool       `json:"job_events"`
-	PipelineEvents           bool       `json:"pipeline_events"`
-	WikiPageEvents           bool       `json:"wiki_page_events"`
-	DeploymentEvents         bool       `json:"deployment_events"`
-	ReleasesEvents           bool       `json:"releases_events"`
-	SubGroupEvents           bool       `json:"subgroup_events"`
-	EnableSSLVerification    bool       `json:"enable_ssl_verification"`
-	AlertStatus              string     `json:"alert_status"`
-	CreatedAt                *time.Time `json:"created_at"`
-	CustomWebhookTemplate    string     `json:"custom_webhook_template"`
+	ID                        int        `json:"id"`
+	URL                       string     `json:"url"`
+	GroupID                   int        `json:"group_id"`
+	PushEvents                bool       `json:"push_events"`
+	PushEventsBranchFilter    string     `json:"push_events_branch_filter"`
+	IssuesEvents              bool       `json:"issues_events"`
+	ConfidentialIssuesEvents  bool       `json:"confidential_issues_events"`
+	ConfidentialNoteEvents    bool       `json:"confidential_note_events"`
+	MergeRequestsEvents       bool       `json:"merge_requests_events"`
+	TagPushEvents             bool       `json:"tag_push_events"`
+	NoteEvents                bool       `json:"note_events"`
+	JobEvents                 bool       `json:"job_events"`
+	PipelineEvents            bool       `json:"pipeline_events"`
+	WikiPageEvents            bool       `json:"wiki_page_events"`
+	DeploymentEvents          bool       `json:"deployment_events"`
+	ReleasesEvents            bool       `json:"releases_events"`
+	SubGroupEvents            bool       `json:"subgroup_events"`
+	MemberEvents              bool       `json:"member_events"`
+	EnableSSLVerification     bool       `json:"enable_ssl_verification"`
+	AlertStatus               string     `json:"alert_status"`
+	CreatedAt                 *time.Time `json:"created_at"`
+	CustomWebhookTemplate     string     `json:"custom_webhook_template"`
+	ResourceAccessTokenEvents bool       `json:"resource_access_token_events"`
 }
 
 // ListGroupHooksOptions represents the available ListGroupHooks() options.
@@ -106,24 +108,26 @@ func (s *GroupsService) GetGroupHook(pid interface{}, hook int, options ...Reque
 //
 // GitLab API docs: https://docs.gitlab.com/ee/api/groups.html#add-group-hook
 type AddGroupHookOptions struct {
-	URL                      *string `url:"url,omitempty" json:"url,omitempty"`
-	PushEvents               *bool   `url:"push_events,omitempty"  json:"push_events,omitempty"`
-	PushEventsBranchFilter   *string `url:"push_events_branch_filter,omitempty"  json:"push_events_branch_filter,omitempty"`
-	IssuesEvents             *bool   `url:"issues_events,omitempty"  json:"issues_events,omitempty"`
-	ConfidentialIssuesEvents *bool   `url:"confidential_issues_events,omitempty"  json:"confidential_issues_events,omitempty"`
-	ConfidentialNoteEvents   *bool   `url:"confidential_note_events,omitempty"  json:"confidential_note_events,omitempty"`
-	MergeRequestsEvents      *bool   `url:"merge_requests_events,omitempty"  json:"merge_requests_events,omitempty"`
-	TagPushEvents            *bool   `url:"tag_push_events,omitempty"  json:"tag_push_events,omitempty"`
-	NoteEvents               *bool   `url:"note_events,omitempty"  json:"note_events,omitempty"`
-	JobEvents                *bool   `url:"job_events,omitempty"  json:"job_events,omitempty"`
-	PipelineEvents           *bool   `url:"pipeline_events,omitempty"  json:"pipeline_events,omitempty"`
-	WikiPageEvents           *bool   `url:"wiki_page_events,omitempty"  json:"wiki_page_events,omitempty"`
-	DeploymentEvents         *bool   `url:"deployment_events,omitempty" json:"deployment_events,omitempty"`
-	ReleasesEvents           *bool   `url:"releases_events,omitempty" json:"releases_events,omitempty"`
-	SubGroupEvents           *bool   `url:"subgroup_events,omitempty" json:"subgroup_events,omitempty"`
-	EnableSSLVerification    *bool   `url:"enable_ssl_verification,omitempty"  json:"enable_ssl_verification,omitempty"`
-	Token                    *string `url:"token,omitempty" json:"token,omitempty"`
-	CustomWebhookTemplate    *string `url:"custom_webhook_template,omitempty" json:"custom_webhook_template,omitempty"`
+	URL                       *string `url:"url,omitempty" json:"url,omitempty"`
+	PushEvents                *bool   `url:"push_events,omitempty"  json:"push_events,omitempty"`
+	PushEventsBranchFilter    *string `url:"push_events_branch_filter,omitempty"  json:"push_events_branch_filter,omitempty"`
+	IssuesEvents              *bool   `url:"issues_events,omitempty"  json:"issues_events,omitempty"`
+	ConfidentialIssuesEvents  *bool   `url:"confidential_issues_events,omitempty"  json:"confidential_issues_events,omitempty"`
+	ConfidentialNoteEvents    *bool   `url:"confidential_note_events,omitempty"  json:"confidential_note_events,omitempty"`
+	MergeRequestsEvents       *bool   `url:"merge_requests_events,omitempty"  json:"merge_requests_events,omitempty"`
+	TagPushEvents             *bool   `url:"tag_push_events,omitempty"  json:"tag_push_events,omitempty"`
+	NoteEvents                *bool   `url:"note_events,omitempty"  json:"note_events,omitempty"`
+	JobEvents                 *bool   `url:"job_events,omitempty"  json:"job_events,omitempty"`
+	PipelineEvents            *bool   `url:"pipeline_events,omitempty"  json:"pipeline_events,omitempty"`
+	WikiPageEvents            *bool   `url:"wiki_page_events,omitempty"  json:"wiki_page_events,omitempty"`
+	DeploymentEvents          *bool   `url:"deployment_events,omitempty" json:"deployment_events,omitempty"`
+	ReleasesEvents            *bool   `url:"releases_events,omitempty" json:"releases_events,omitempty"`
+	SubGroupEvents            *bool   `url:"subgroup_events,omitempty" json:"subgroup_events,omitempty"`
+	MemberEvents              *bool   `url:"member_events,omitempty" json:"member_events,omitempty"`
+	EnableSSLVerification     *bool   `url:"enable_ssl_verification,omitempty"  json:"enable_ssl_verification,omitempty"`
+	Token                     *string `url:"token,omitempty" json:"token,omitempty"`
+	ResourceAccessTokenEvents *bool   `url:"resource_access_token_events,omitempty" json:"resource_access_token_events,omitempty"`
+	CustomWebhookTemplate     *string `url:"custom_webhook_template,omitempty" json:"custom_webhook_template,omitempty"`
 }
 
 // AddGroupHook create a new group scoped webhook.
@@ -155,24 +159,26 @@ func (s *GroupsService) AddGroupHook(gid interface{}, opt *AddGroupHookOptions,
 // GitLab API docs:
 // https://docs.gitlab.com/ee/api/groups.html#edit-group-hook
 type EditGroupHookOptions struct {
-	URL                      *string `url:"url,omitempty" json:"url,omitempty"`
-	PushEvents               *bool   `url:"push_events,omitempty" json:"push_events,omitempty"`
-	PushEventsBranchFilter   *string `url:"push_events_branch_filter,omitempty"  json:"push_events_branch_filter,omitempty"`
-	IssuesEvents             *bool   `url:"issues_events,omitempty" json:"issues_events,omitempty"`
-	ConfidentialIssuesEvents *bool   `url:"confidential_issues_events,omitempty" json:"confidential_issues_events,omitempty"`
-	ConfidentialNoteEvents   *bool   `url:"confidential_note_events,omitempty" json:"confidential_note_events,omitempty"`
-	MergeRequestsEvents      *bool   `url:"merge_requests_events,omitempty" json:"merge_requests_events,omitempty"`
-	TagPushEvents            *bool   `url:"tag_push_events,omitempty" json:"tag_push_events,omitempty"`
-	NoteEvents               *bool   `url:"note_events,omitempty" json:"note_events,omitempty"`
-	JobEvents                *bool   `url:"job_events,omitempty" json:"job_events,omitempty"`
-	PipelineEvents           *bool   `url:"pipeline_events,omitempty" json:"pipeline_events,omitempty"`
-	WikiPageEvents           *bool   `url:"wiki_page_events,omitempty" json:"wiki_page_events,omitempty"`
-	DeploymentEvents         *bool   `url:"deployment_events,omitempty" json:"deployment_events,omitempty"`
-	ReleasesEvents           *bool   `url:"releases_events,omitempty" json:"releases_events,omitempty"`
-	SubGroupEvents           *bool   `url:"subgroup_events,omitempty" json:"subgroup_events,omitempty"`
-	EnableSSLVerification    *bool   `url:"enable_ssl_verification,omitempty" json:"enable_ssl_verification,omitempty"`
-	Token                    *string `url:"token,omitempty" json:"token,omitempty"`
-	CustomWebhookTemplate    *string `url:"custom_webhook_template,omitempty" json:"custom_webhook_template,omitempty"`
+	URL                       *string `url:"url,omitempty" json:"url,omitempty"`
+	PushEvents                *bool   `url:"push_events,omitempty" json:"push_events,omitempty"`
+	PushEventsBranchFilter    *string `url:"push_events_branch_filter,omitempty"  json:"push_events_branch_filter,omitempty"`
+	IssuesEvents              *bool   `url:"issues_events,omitempty" json:"issues_events,omitempty"`
+	ConfidentialIssuesEvents  *bool   `url:"confidential_issues_events,omitempty" json:"confidential_issues_events,omitempty"`
+	ConfidentialNoteEvents    *bool   `url:"confidential_note_events,omitempty" json:"confidential_note_events,omitempty"`
+	MergeRequestsEvents       *bool   `url:"merge_requests_events,omitempty" json:"merge_requests_events,omitempty"`
+	TagPushEvents             *bool   `url:"tag_push_events,omitempty" json:"tag_push_events,omitempty"`
+	NoteEvents                *bool   `url:"note_events,omitempty" json:"note_events,omitempty"`
+	JobEvents                 *bool   `url:"job_events,omitempty" json:"job_events,omitempty"`
+	PipelineEvents            *bool   `url:"pipeline_events,omitempty" json:"pipeline_events,omitempty"`
+	WikiPageEvents            *bool   `url:"wiki_page_events,omitempty" json:"wiki_page_events,omitempty"`
+	DeploymentEvents          *bool   `url:"deployment_events,omitempty" json:"deployment_events,omitempty"`
+	ReleasesEvents            *bool   `url:"releases_events,omitempty" json:"releases_events,omitempty"`
+	SubGroupEvents            *bool   `url:"subgroup_events,omitempty" json:"subgroup_events,omitempty"`
+	MemberEvents              *bool   `url:"member_events,omitempty" json:"member_events,omitempty"`
+	EnableSSLVerification     *bool   `url:"enable_ssl_verification,omitempty" json:"enable_ssl_verification,omitempty"`
+	Token                     *string `url:"token,omitempty" json:"token,omitempty"`
+	ResourceAccessTokenEvents *bool   `url:"resource_access_token_events,omitempty" json:"resource_access_token_events,omitempty"`
+	CustomWebhookTemplate     *string `url:"custom_webhook_template,omitempty" json:"custom_webhook_template,omitempty"`
 }
 
 // EditGroupHook edits a hook for a specified group.
diff --git a/group_members.go b/group_members.go
index cc7bbd6..f0018ca 100644
--- a/group_members.go
+++ b/group_members.go
@@ -56,7 +56,6 @@ type GroupMember struct {
 	AccessLevel       AccessLevelValue         `json:"access_level"`
 	Email             string                   `json:"email,omitempty"`
 	GroupSAMLIdentity *GroupMemberSAMLIdentity `json:"group_saml_identity"`
-	MemberRole        *MemberRole              `json:"member_role"`
 }
 
 // ListGroupMembersOptions represents the available ListGroupMembers() and
diff --git a/group_protected_environments.go b/group_protected_environments.go
index addc383..53bee70 100644
--- a/group_protected_environments.go
+++ b/group_protected_environments.go
@@ -52,7 +52,6 @@ type GroupEnvironmentAccessDescription struct {
 	AccessLevelDescription string           `json:"access_level_description"`
 	UserID                 int              `json:"user_id"`
 	GroupID                int              `json:"group_id"`
-	GroupInheritanceType   int              `json:"group_inheritance_type"`
 }
 
 // GroupEnvironmentApprovalRule represents the approval rules for a group-level
@@ -147,10 +146,9 @@ type ProtectGroupEnvironmentOptions struct {
 // GitLab API docs:
 // https://docs.gitlab.com/ee/api/group_protected_environments.html#protect-a-single-environment
 type GroupEnvironmentAccessOptions struct {
-	AccessLevel          *AccessLevelValue `url:"access_level,omitempty" json:"access_level,omitempty"`
-	UserID               *int              `url:"user_id,omitempty" json:"user_id,omitempty"`
-	GroupID              *int              `url:"group_id,omitempty" json:"group_id,omitempty"`
-	GroupInheritanceType *int              `url:"group_inheritance_type,omitempty" json:"group_inheritance_type,omitempty"`
+	AccessLevel *AccessLevelValue `url:"access_level,omitempty" json:"access_level,omitempty"`
+	UserID      *int              `url:"user_id,omitempty" json:"user_id,omitempty"`
+	GroupID     *int              `url:"group_id,omitempty" json:"group_id,omitempty"`
 }
 
 // GroupEnvironmentApprovalRuleOptions represents the approval rules for a
@@ -210,12 +208,11 @@ type UpdateGroupProtectedEnvironmentOptions struct {
 // GitLab API docs:
 // https://docs.gitlab.com/ee/api/group_protected_environments.html#update-a-protected-environment
 type UpdateGroupEnvironmentAccessOptions struct {
-	AccessLevel          *AccessLevelValue `url:"access_level,omitempty" json:"access_level,omitempty"`
-	ID                   *int              `url:"id,omitempty" json:"id,omitempty"`
-	UserID               *int              `url:"user_id,omitempty" json:"user_id,omitempty"`
-	GroupID              *int              `url:"group_id,omitempty" json:"group_id,omitempty"`
-	GroupInheritanceType *int              `url:"group_inheritance_type,omitempty" json:"group_inheritance_type,omitempty"`
-	Destroy              *bool             `url:"_destroy,omitempty" json:"_destroy,omitempty"`
+	AccessLevel *AccessLevelValue `url:"access_level,omitempty" json:"access_level,omitempty"`
+	ID          *int              `url:"id,omitempty" json:"id,omitempty"`
+	UserID      *int              `url:"user_id,omitempty" json:"user_id,omitempty"`
+	GroupID     *int              `url:"group_id,omitempty" json:"group_id,omitempty"`
+	Destroy     *bool             `url:"_destroy,omitempty" json:"_destroy,omitempty"`
 }
 
 // UpdateGroupEnvironmentApprovalRuleOptions represents the updates to the
diff --git a/group_serviceaccounts.go b/group_serviceaccounts.go
index 3ccb41b..4acb0b1 100644
--- a/group_serviceaccounts.go
+++ b/group_serviceaccounts.go
@@ -62,9 +62,8 @@ func (s *GroupsService) CreateServiceAccount(gid interface{}, options ...Request
 // GitLab API docs:
 // https://docs.gitlab.com/ee/api/groups.html#create-personal-access-token-for-service-account-user
 type CreateServiceAccountPersonalAccessTokenOptions struct {
-	Scopes    *[]string `url:"scopes,omitempty" json:"scopes,omitempty"`
-	Name      *string   `url:"name,omitempty" json:"name,omitempty"`
-	ExpiresAt *ISOTime  `url:"expires_at,omitempty" json:"expires_at,omitempty"`
+	Scopes *[]string `url:"scopes,omitempty" json:"scopes,omitempty"`
+	Name   *string   `url:"name,omitempty" json:"name,omitempty"`
 }
 
 // CreateServiceAccountPersonalAccessToken add a new Personal Access Token for a
diff --git a/groups.go b/groups.go
index a62750b..1040684 100644
--- a/groups.go
+++ b/groups.go
@@ -64,7 +64,7 @@ type Group struct {
 	ProjectCreationLevel    ProjectCreationLevelValue  `json:"project_creation_level"`
 	AutoDevopsEnabled       bool                       `json:"auto_devops_enabled"`
 	SubGroupCreationLevel   SubGroupCreationLevelValue `json:"subgroup_creation_level"`
-	EmailsEnabled           bool                       `json:"emails_enabled"`
+	EmailsDisabled          bool                       `json:"emails_disabled"`
 	MentionsDisabled        bool                       `json:"mentions_disabled"`
 	RunnersToken            string                     `json:"runners_token"`
 	SharedProjects          []*Project                 `json:"shared_projects"`
@@ -87,9 +87,6 @@ type Group struct {
 	CreatedAt                      *time.Time         `json:"created_at"`
 	IPRestrictionRanges            string             `json:"ip_restriction_ranges"`
 	WikiAccessLevel                AccessControlValue `json:"wiki_access_level"`
-
-	// Deprecated: Use EmailsEnabled instead
-	EmailsDisabled bool `json:"emails_disabled"`
 }
 
 // GroupAvatar represents a GitLab group avatar.
@@ -350,7 +347,7 @@ type CreateGroupOptions struct {
 	ProjectCreationLevel           *ProjectCreationLevelValue  `url:"project_creation_level,omitempty" json:"project_creation_level,omitempty"`
 	AutoDevopsEnabled              *bool                       `url:"auto_devops_enabled,omitempty" json:"auto_devops_enabled,omitempty"`
 	SubGroupCreationLevel          *SubGroupCreationLevelValue `url:"subgroup_creation_level,omitempty" json:"subgroup_creation_level,omitempty"`
-	EmailsEnabled                  *bool                       `url:"emails_enabled,omitempty" json:"emails_enabled,omitempty"`
+	EmailsDisabled                 *bool                       `url:"emails_disabled,omitempty" json:"emails_disabled,omitempty"`
 	MentionsDisabled               *bool                       `url:"mentions_disabled,omitempty" json:"mentions_disabled,omitempty"`
 	LFSEnabled                     *bool                       `url:"lfs_enabled,omitempty" json:"lfs_enabled,omitempty"`
 	DefaultBranchProtection        *int                        `url:"default_branch_protection,omitempty" json:"default_branch_protection"`
@@ -360,9 +357,6 @@ type CreateGroupOptions struct {
 	ExtraSharedRunnersMinutesLimit *int                        `url:"extra_shared_runners_minutes_limit,omitempty" json:"extra_shared_runners_minutes_limit,omitempty"`
 	IPRestrictionRanges            *string                     `url:"ip_restriction_ranges,omitempty" json:"ip_restriction_ranges,omitempty"`
 	WikiAccessLevel                *AccessControlValue         `url:"wiki_access_level,omitempty" json:"wiki_access_level,omitempty"`
-
-	// Deprecated: Use EmailsEnabled instead
-	EmailsDisabled *bool `url:"emails_disabled,omitempty" json:"emails_disabled,omitempty"`
 }
 
 // CreateGroup creates a new project group. Available only for users who can
@@ -479,7 +473,7 @@ type UpdateGroupOptions struct {
 	ProjectCreationLevel                 *ProjectCreationLevelValue  `url:"project_creation_level,omitempty" json:"project_creation_level,omitempty"`
 	AutoDevopsEnabled                    *bool                       `url:"auto_devops_enabled,omitempty" json:"auto_devops_enabled,omitempty"`
 	SubGroupCreationLevel                *SubGroupCreationLevelValue `url:"subgroup_creation_level,omitempty" json:"subgroup_creation_level,omitempty"`
-	EmailsEnabled                        *bool                       `url:"emails_enabled,omitempty" json:"emails_enabled,omitempty"`
+	EmailsDisabled                       *bool                       `url:"emails_disabled,omitempty" json:"emails_disabled,omitempty"`
 	MentionsDisabled                     *bool                       `url:"mentions_disabled,omitempty" json:"mentions_disabled,omitempty"`
 	LFSEnabled                           *bool                       `url:"lfs_enabled,omitempty" json:"lfs_enabled,omitempty"`
 	RequestAccessEnabled                 *bool                       `url:"request_access_enabled,omitempty" json:"request_access_enabled,omitempty"`
@@ -492,9 +486,6 @@ type UpdateGroupOptions struct {
 	PreventSharingGroupsOutsideHierarchy *bool                       `url:"prevent_sharing_groups_outside_hierarchy,omitempty" json:"prevent_sharing_groups_outside_hierarchy,omitempty"`
 	IPRestrictionRanges                  *string                     `url:"ip_restriction_ranges,omitempty" json:"ip_restriction_ranges,omitempty"`
 	WikiAccessLevel                      *AccessControlValue         `url:"wiki_access_level,omitempty" json:"wiki_access_level,omitempty"`
-
-	// Deprecated: Use EmailsEnabled instead
-	EmailsDisabled *bool `url:"emails_disabled,omitempty" json:"emails_disabled,omitempty"`
 }
 
 // UpdateGroup updates an existing group; only available to group owners and
diff --git a/member_roles.go b/member_roles.go
index cefb94b..e3f1285 100644
--- a/member_roles.go
+++ b/member_roles.go
@@ -22,18 +22,12 @@ type MemberRole struct {
 	Description              string           `json:"description,omitempty"`
 	GroupId                  int              `json:"group_id"`
 	BaseAccessLevel          AccessLevelValue `json:"base_access_level"`
-	AdminCICDVariables       bool             `json:"admin_cicd_variables,omitempty"`
-	AdminMergeRequests       bool             `json:"admin_merge_request,omitempty"`
-	AdminTerraformState      bool             `json:"admin_terraform_state,omitempty"`
+	AdminMergeRequests       bool             `json:"admin_merge_requests,omitempty"`
 	AdminVulnerability       bool             `json:"admin_vulnerability,omitempty"`
 	ReadCode                 bool             `json:"read_code,omitempty"`
 	ReadDependency           bool             `json:"read_dependency,omitempty"`
 	ReadVulnerability        bool             `json:"read_vulnerability,omitempty"`
-	AdminGroupMembers        bool             `json:"admin_group_member,omitempty"`
-	ManageProjectAccessToken bool             `json:"manage_project_access_tokens,omitempty"`
-	ArchiveProject           bool             `json:"archive_project,omitempty"`
-	RemoveProject            bool             `json:"remove_project,omitempty"`
-	ManageGroupAccesToken    bool             `json:"manage_group_access_tokens,omitempty"`
+	ManageProjectAccessToken bool             `json:"manage_project_access_token,omitempty"`
 }
 
 // ListMemberRoles gets a list of member roles for a specified group.
diff --git a/merge_request_approvals.go b/merge_request_approvals.go
index 7eadc82..0da0af3 100644
--- a/merge_request_approvals.go
+++ b/merge_request_approvals.go
@@ -180,26 +180,6 @@ func (s *MergeRequestApprovalsService) UnapproveMergeRequest(pid interface{}, mr
 	return s.client.Do(req, nil)
 }
 
-// ResetApprovalsOfMergeRequest clear all approvals of merge request on GitLab.
-// Available only for bot users based on project or group tokens.
-//
-// GitLab API docs:
-// https://docs.gitlab.com/ee/api/merge_request_approvals.html#reset-approvals-of-a-merge-request
-func (s *MergeRequestApprovalsService) ResetApprovalsOfMergeRequest(pid interface{}, mr int, options ...RequestOptionFunc) (*Response, error) {
-	project, err := parseID(pid)
-	if err != nil {
-		return nil, err
-	}
-	u := fmt.Sprintf("projects/%s/merge_requests/%d/reset_approvals", PathEscape(project), mr)
-
-	req, err := s.client.NewRequest(http.MethodPut, u, nil, options)
-	if err != nil {
-		return nil, err
-	}
-
-	return s.client.Do(req, nil)
-}
-
 // ChangeMergeRequestApprovalConfigurationOptions represents the available
 // ChangeMergeRequestApprovalConfiguration() options.
 //
diff --git a/merge_requests.go b/merge_requests.go
index a9e8d2e..9d88dbc 100644
--- a/merge_requests.go
+++ b/merge_requests.go
@@ -682,20 +682,19 @@ func (s *MergeRequestsService) GetIssuesClosedOnMerge(pid interface{}, mergeRequ
 // GitLab API docs:
 // https://docs.gitlab.com/ee/api/merge_requests.html#create-mr
 type CreateMergeRequestOptions struct {
-	Title                *string       `url:"title,omitempty" json:"title,omitempty"`
-	Description          *string       `url:"description,omitempty" json:"description,omitempty"`
-	SourceBranch         *string       `url:"source_branch,omitempty" json:"source_branch,omitempty"`
-	TargetBranch         *string       `url:"target_branch,omitempty" json:"target_branch,omitempty"`
-	Labels               *LabelOptions `url:"labels,comma,omitempty" json:"labels,omitempty"`
-	AssigneeID           *int          `url:"assignee_id,omitempty" json:"assignee_id,omitempty"`
-	AssigneeIDs          *[]int        `url:"assignee_ids,omitempty" json:"assignee_ids,omitempty"`
-	ReviewerIDs          *[]int        `url:"reviewer_ids,omitempty" json:"reviewer_ids,omitempty"`
-	TargetProjectID      *int          `url:"target_project_id,omitempty" json:"target_project_id,omitempty"`
-	MilestoneID          *int          `url:"milestone_id,omitempty" json:"milestone_id,omitempty"`
-	RemoveSourceBranch   *bool         `url:"remove_source_branch,omitempty" json:"remove_source_branch,omitempty"`
-	Squash               *bool         `url:"squash,omitempty" json:"squash,omitempty"`
-	AllowCollaboration   *bool         `url:"allow_collaboration,omitempty" json:"allow_collaboration,omitempty"`
-	ApprovalsBeforeMerge *int          `url:"approvals_before_merge,omitempty" json:"approvals_before_merge,omitempty"`
+	Title              *string       `url:"title,omitempty" json:"title,omitempty"`
+	Description        *string       `url:"description,omitempty" json:"description,omitempty"`
+	SourceBranch       *string       `url:"source_branch,omitempty" json:"source_branch,omitempty"`
+	TargetBranch       *string       `url:"target_branch,omitempty" json:"target_branch,omitempty"`
+	Labels             *LabelOptions `url:"labels,comma,omitempty" json:"labels,omitempty"`
+	AssigneeID         *int          `url:"assignee_id,omitempty" json:"assignee_id,omitempty"`
+	AssigneeIDs        *[]int        `url:"assignee_ids,omitempty" json:"assignee_ids,omitempty"`
+	ReviewerIDs        *[]int        `url:"reviewer_ids,omitempty" json:"reviewer_ids,omitempty"`
+	TargetProjectID    *int          `url:"target_project_id,omitempty" json:"target_project_id,omitempty"`
+	MilestoneID        *int          `url:"milestone_id,omitempty" json:"milestone_id,omitempty"`
+	RemoveSourceBranch *bool         `url:"remove_source_branch,omitempty" json:"remove_source_branch,omitempty"`
+	Squash             *bool         `url:"squash,omitempty" json:"squash,omitempty"`
+	AllowCollaboration *bool         `url:"allow_collaboration,omitempty" json:"allow_collaboration,omitempty"`
 }
 
 // CreateMergeRequest creates a new merge request.
@@ -861,29 +860,20 @@ func (s *MergeRequestsService) CancelMergeWhenPipelineSucceeds(pid interface{},
 	return m, resp, nil
 }
 
-// RebaseMergeRequestOptions represents the available RebaseMergeRequest()
-// options.
-//
-// GitLab API docs:
-// https://docs.gitlab.com/ee/api/merge_requests.html#rebase-a-merge-request
-type RebaseMergeRequestOptions struct {
-	SkipCI *bool `url:"skip_ci,omitempty" json:"skip_ci,omitempty"`
-}
-
 // RebaseMergeRequest automatically rebases the source_branch of the merge
 // request against its target_branch. If you don’t have permissions to push
 // to the merge request’s source branch, you’ll get a 403 Forbidden response.
 //
 // GitLab API docs:
 // https://docs.gitlab.com/ee/api/merge_requests.html#rebase-a-merge-request
-func (s *MergeRequestsService) RebaseMergeRequest(pid interface{}, mergeRequest int, opt *RebaseMergeRequestOptions, options ...RequestOptionFunc) (*Response, error) {
+func (s *MergeRequestsService) RebaseMergeRequest(pid interface{}, mergeRequest int, options ...RequestOptionFunc) (*Response, error) {
 	project, err := parseID(pid)
 	if err != nil {
 		return nil, err
 	}
 	u := fmt.Sprintf("projects/%s/merge_requests/%d/rebase", PathEscape(project), mergeRequest)
 
-	req, err := s.client.NewRequest(http.MethodPut, u, opt, options)
+	req, err := s.client.NewRequest(http.MethodPut, u, nil, options)
 	if err != nil {
 		return nil, err
 	}
diff --git a/packages.go b/packages.go
index a6b252e..fb7e2d1 100644
--- a/packages.go
+++ b/packages.go
@@ -89,15 +89,14 @@ func (s PackageTag) String() string {
 //
 // GitLab API docs: https://docs.gitlab.com/ee/api/packages.html
 type PackageFile struct {
-	ID         int         `json:"id"`
-	PackageID  int         `json:"package_id"`
-	CreatedAt  *time.Time  `json:"created_at"`
-	FileName   string      `json:"file_name"`
-	Size       int         `json:"size"`
-	FileMD5    string      `json:"file_md5"`
-	FileSHA1   string      `json:"file_sha1"`
-	FileSHA256 string      `json:"file_sha256"`
-	Pipeline   *[]Pipeline `json:"pipelines"`
+	ID        int         `json:"id"`
+	PackageID int         `json:"package_id"`
+	CreatedAt *time.Time  `json:"created_at"`
+	FileName  string      `json:"file_name"`
+	Size      int         `json:"size"`
+	FileMD5   string      `json:"file_md5"`
+	FileSHA1  string      `json:"file_sha1"`
+	Pipeline  *[]Pipeline `json:"pipelines"`
 }
 
 func (s PackageFile) String() string {
diff --git a/projects.go b/projects.go
index 8edd9cc..91961ac 100644
--- a/projects.go
+++ b/projects.go
@@ -168,7 +168,6 @@ type Project struct {
 	SecurityAndComplianceAccessLevel         AccessControlValue `json:"security_and_compliance_access_level"`
 	MergeRequestDefaultTargetSelf            bool               `json:"mr_default_target_self"`
 	ModelExperimentsAccessLevel              AccessControlValue `json:"model_experiments_access_level"`
-	ModelRegistryAccessLevel                 AccessControlValue `json:"model_registry_access_level"`
 
 	// Deprecated: Use EmailsEnabled instead
 	EmailsDisabled bool `json:"emails_disabled"`
@@ -641,7 +640,6 @@ type CreateProjectOptions struct {
 	Mirror                                    *bool                                `url:"mirror,omitempty" json:"mirror,omitempty"`
 	MirrorTriggerBuilds                       *bool                                `url:"mirror_trigger_builds,omitempty" json:"mirror_trigger_builds,omitempty"`
 	ModelExperimentsAccessLevel               *AccessControlValue                  `url:"model_experiments_access_level,omitempty" json:"model_experiments_access_level,omitempty"`
-	ModelRegistryAccessLevel                  *AccessControlValue                  `url:"model_registry_access_level,omitempty" json:"model_registry_access_level,omitempty"`
 	Name                                      *string                              `url:"name,omitempty" json:"name,omitempty"`
 	NamespaceID                               *int                                 `url:"namespace_id,omitempty" json:"namespace_id,omitempty"`
 	OnlyAllowMergeIfAllDiscussionsAreResolved *bool                                `url:"only_allow_merge_if_all_discussions_are_resolved,omitempty" json:"only_allow_merge_if_all_discussions_are_resolved,omitempty"`
@@ -875,7 +873,6 @@ type EditProjectOptions struct {
 	MirrorTriggerBuilds                       *bool                                `url:"mirror_trigger_builds,omitempty" json:"mirror_trigger_builds,omitempty"`
 	MirrorUserID                              *int                                 `url:"mirror_user_id,omitempty" json:"mirror_user_id,omitempty"`
 	ModelExperimentsAccessLevel               *AccessControlValue                  `url:"model_experiments_access_level,omitempty" json:"model_experiments_access_level,omitempty"`
-	ModelRegistryAccessLevel                  *AccessControlValue                  `url:"model_registry_access_level,omitempty" json:"model_registry_access_level,omitempty"`
 	Name                                      *string                              `url:"name,omitempty" json:"name,omitempty"`
 	OnlyAllowMergeIfAllDiscussionsAreResolved *bool                                `url:"only_allow_merge_if_all_discussions_are_resolved,omitempty" json:"only_allow_merge_if_all_discussions_are_resolved,omitempty"`
 	OnlyAllowMergeIfPipelineSucceeds          *bool                                `url:"only_allow_merge_if_pipeline_succeeds,omitempty" json:"only_allow_merge_if_pipeline_succeeds,omitempty"`
@@ -1202,25 +1199,26 @@ type ProjectMember struct {
 // GitLab API docs:
 // https://docs.gitlab.com/ee/api/projects.html#list-project-hooks
 type ProjectHook struct {
-	ID                       int        `json:"id"`
-	URL                      string     `json:"url"`
-	ConfidentialNoteEvents   bool       `json:"confidential_note_events"`
-	ProjectID                int        `json:"project_id"`
-	PushEvents               bool       `json:"push_events"`
-	PushEventsBranchFilter   string     `json:"push_events_branch_filter"`
-	IssuesEvents             bool       `json:"issues_events"`
-	ConfidentialIssuesEvents bool       `json:"confidential_issues_events"`
-	MergeRequestsEvents      bool       `json:"merge_requests_events"`
-	TagPushEvents            bool       `json:"tag_push_events"`
-	NoteEvents               bool       `json:"note_events"`
-	JobEvents                bool       `json:"job_events"`
-	PipelineEvents           bool       `json:"pipeline_events"`
-	WikiPageEvents           bool       `json:"wiki_page_events"`
-	DeploymentEvents         bool       `json:"deployment_events"`
-	ReleasesEvents           bool       `json:"releases_events"`
-	EnableSSLVerification    bool       `json:"enable_ssl_verification"`
-	CreatedAt                *time.Time `json:"created_at"`
-	CustomWebhookTemplate    string     `json:"custom_webhook_template"`
+	ID                        int        `json:"id"`
+	URL                       string     `json:"url"`
+	ConfidentialNoteEvents    bool       `json:"confidential_note_events"`
+	ProjectID                 int        `json:"project_id"`
+	PushEvents                bool       `json:"push_events"`
+	PushEventsBranchFilter    string     `json:"push_events_branch_filter"`
+	IssuesEvents              bool       `json:"issues_events"`
+	ConfidentialIssuesEvents  bool       `json:"confidential_issues_events"`
+	MergeRequestsEvents       bool       `json:"merge_requests_events"`
+	TagPushEvents             bool       `json:"tag_push_events"`
+	NoteEvents                bool       `json:"note_events"`
+	JobEvents                 bool       `json:"job_events"`
+	PipelineEvents            bool       `json:"pipeline_events"`
+	WikiPageEvents            bool       `json:"wiki_page_events"`
+	DeploymentEvents          bool       `json:"deployment_events"`
+	ReleasesEvents            bool       `json:"releases_events"`
+	EnableSSLVerification     bool       `json:"enable_ssl_verification"`
+	CreatedAt                 *time.Time `json:"created_at"`
+	ResourceAccessTokenEvents bool       `json:"resource_access_token_events"`
+	CustomWebhookTemplate     string     `json:"custom_webhook_template"`
 }
 
 // ListProjectHooksOptions represents the available ListProjectHooks() options.
@@ -1283,23 +1281,24 @@ func (s *ProjectsService) GetProjectHook(pid interface{}, hook int, options ...R
 // GitLab API docs:
 // https://docs.gitlab.com/ee/api/projects.html#add-project-hook
 type AddProjectHookOptions struct {
-	ConfidentialIssuesEvents *bool   `url:"confidential_issues_events,omitempty" json:"confidential_issues_events,omitempty"`
-	ConfidentialNoteEvents   *bool   `url:"confidential_note_events,omitempty" json:"confidential_note_events,omitempty"`
-	DeploymentEvents         *bool   `url:"deployment_events,omitempty" json:"deployment_events,omitempty"`
-	EnableSSLVerification    *bool   `url:"enable_ssl_verification,omitempty" json:"enable_ssl_verification,omitempty"`
-	IssuesEvents             *bool   `url:"issues_events,omitempty" json:"issues_events,omitempty"`
-	JobEvents                *bool   `url:"job_events,omitempty" json:"job_events,omitempty"`
-	MergeRequestsEvents      *bool   `url:"merge_requests_events,omitempty" json:"merge_requests_events,omitempty"`
-	NoteEvents               *bool   `url:"note_events,omitempty" json:"note_events,omitempty"`
-	PipelineEvents           *bool   `url:"pipeline_events,omitempty" json:"pipeline_events,omitempty"`
-	PushEvents               *bool   `url:"push_events,omitempty" json:"push_events,omitempty"`
-	PushEventsBranchFilter   *string `url:"push_events_branch_filter,omitempty" json:"push_events_branch_filter,omitempty"`
-	ReleasesEvents           *bool   `url:"releases_events,omitempty" json:"releases_events,omitempty"`
-	TagPushEvents            *bool   `url:"tag_push_events,omitempty" json:"tag_push_events,omitempty"`
-	Token                    *string `url:"token,omitempty" json:"token,omitempty"`
-	URL                      *string `url:"url,omitempty" json:"url,omitempty"`
-	WikiPageEvents           *bool   `url:"wiki_page_events,omitempty" json:"wiki_page_events,omitempty"`
-	CustomWebhookTemplate    *string `url:"custom_webhook_template,omitempty" json:"custom_webhook_template,omitempty"`
+	ConfidentialIssuesEvents  *bool   `url:"confidential_issues_events,omitempty" json:"confidential_issues_events,omitempty"`
+	ConfidentialNoteEvents    *bool   `url:"confidential_note_events,omitempty" json:"confidential_note_events,omitempty"`
+	DeploymentEvents          *bool   `url:"deployment_events,omitempty" json:"deployment_events,omitempty"`
+	EnableSSLVerification     *bool   `url:"enable_ssl_verification,omitempty" json:"enable_ssl_verification,omitempty"`
+	IssuesEvents              *bool   `url:"issues_events,omitempty" json:"issues_events,omitempty"`
+	JobEvents                 *bool   `url:"job_events,omitempty" json:"job_events,omitempty"`
+	MergeRequestsEvents       *bool   `url:"merge_requests_events,omitempty" json:"merge_requests_events,omitempty"`
+	NoteEvents                *bool   `url:"note_events,omitempty" json:"note_events,omitempty"`
+	PipelineEvents            *bool   `url:"pipeline_events,omitempty" json:"pipeline_events,omitempty"`
+	PushEvents                *bool   `url:"push_events,omitempty" json:"push_events,omitempty"`
+	PushEventsBranchFilter    *string `url:"push_events_branch_filter,omitempty" json:"push_events_branch_filter,omitempty"`
+	ReleasesEvents            *bool   `url:"releases_events,omitempty" json:"releases_events,omitempty"`
+	TagPushEvents             *bool   `url:"tag_push_events,omitempty" json:"tag_push_events,omitempty"`
+	Token                     *string `url:"token,omitempty" json:"token,omitempty"`
+	URL                       *string `url:"url,omitempty" json:"url,omitempty"`
+	WikiPageEvents            *bool   `url:"wiki_page_events,omitempty" json:"wiki_page_events,omitempty"`
+	ResourceAccessTokenEvents *bool   `url:"resource_access_token_events,omitempty" json:"resource_access_token_events,omitempty"`
+	CustomWebhookTemplate     *string `url:"custom_webhook_template,omitempty" json:"custom_webhook_template,omitempty"`
 }
 
 // AddProjectHook adds a hook to a specified project.
@@ -1332,23 +1331,24 @@ func (s *ProjectsService) AddProjectHook(pid interface{}, opt *AddProjectHookOpt
 // GitLab API docs:
 // https://docs.gitlab.com/ee/api/projects.html#edit-project-hook
 type EditProjectHookOptions struct {
-	ConfidentialIssuesEvents *bool   `url:"confidential_issues_events,omitempty" json:"confidential_issues_events,omitempty"`
-	ConfidentialNoteEvents   *bool   `url:"confidential_note_events,omitempty" json:"confidential_note_events,omitempty"`
-	DeploymentEvents         *bool   `url:"deployment_events,omitempty" json:"deployment_events,omitempty"`
-	EnableSSLVerification    *bool   `url:"enable_ssl_verification,omitempty" json:"enable_ssl_verification,omitempty"`
-	IssuesEvents             *bool   `url:"issues_events,omitempty" json:"issues_events,omitempty"`
-	JobEvents                *bool   `url:"job_events,omitempty" json:"job_events,omitempty"`
-	MergeRequestsEvents      *bool   `url:"merge_requests_events,omitempty" json:"merge_requests_events,omitempty"`
-	NoteEvents               *bool   `url:"note_events,omitempty" json:"note_events,omitempty"`
-	PipelineEvents           *bool   `url:"pipeline_events,omitempty" json:"pipeline_events,omitempty"`
-	PushEvents               *bool   `url:"push_events,omitempty" json:"push_events,omitempty"`
-	PushEventsBranchFilter   *string `url:"push_events_branch_filter,omitempty" json:"push_events_branch_filter,omitempty"`
-	ReleasesEvents           *bool   `url:"releases_events,omitempty" json:"releases_events,omitempty"`
-	TagPushEvents            *bool   `url:"tag_push_events,omitempty" json:"tag_push_events,omitempty"`
-	Token                    *string `url:"token,omitempty" json:"token,omitempty"`
-	URL                      *string `url:"url,omitempty" json:"url,omitempty"`
-	WikiPageEvents           *bool   `url:"wiki_page_events,omitempty" json:"wiki_page_events,omitempty"`
-	CustomWebhookTemplate    *string `url:"custom_webhook_template,omitempty" json:"custom_webhook_template,omitempty"`
+	ConfidentialIssuesEvents  *bool   `url:"confidential_issues_events,omitempty" json:"confidential_issues_events,omitempty"`
+	ConfidentialNoteEvents    *bool   `url:"confidential_note_events,omitempty" json:"confidential_note_events,omitempty"`
+	DeploymentEvents          *bool   `url:"deployment_events,omitempty" json:"deployment_events,omitempty"`
+	EnableSSLVerification     *bool   `url:"enable_ssl_verification,omitempty" json:"enable_ssl_verification,omitempty"`
+	IssuesEvents              *bool   `url:"issues_events,omitempty" json:"issues_events,omitempty"`
+	JobEvents                 *bool   `url:"job_events,omitempty" json:"job_events,omitempty"`
+	MergeRequestsEvents       *bool   `url:"merge_requests_events,omitempty" json:"merge_requests_events,omitempty"`
+	NoteEvents                *bool   `url:"note_events,omitempty" json:"note_events,omitempty"`
+	PipelineEvents            *bool   `url:"pipeline_events,omitempty" json:"pipeline_events,omitempty"`
+	PushEvents                *bool   `url:"push_events,omitempty" json:"push_events,omitempty"`
+	PushEventsBranchFilter    *string `url:"push_events_branch_filter,omitempty" json:"push_events_branch_filter,omitempty"`
+	ReleasesEvents            *bool   `url:"releases_events,omitempty" json:"releases_events,omitempty"`
+	TagPushEvents             *bool   `url:"tag_push_events,omitempty" json:"tag_push_events,omitempty"`
+	Token                     *string `url:"token,omitempty" json:"token,omitempty"`
+	URL                       *string `url:"url,omitempty" json:"url,omitempty"`
+	WikiPageEvents            *bool   `url:"wiki_page_events,omitempty" json:"wiki_page_events,omitempty"`
+	ResourceAccessTokenEvents *bool   `url:"resource_access_token_events,omitempty" json:"resource_access_token_events,omitempty"`
+	CustomWebhookTemplate     *string `url:"custom_webhook_template,omitempty" json:"custom_webhook_template,omitempty"`
 }
 
 // EditProjectHook edits a hook for a specified project.
diff --git a/protected_environments.go b/protected_environments.go
index 50ee311..9b0fd62 100644
--- a/protected_environments.go
+++ b/protected_environments.go
@@ -52,7 +52,6 @@ type EnvironmentAccessDescription struct {
 	AccessLevelDescription string           `json:"access_level_description"`
 	UserID                 int              `json:"user_id"`
 	GroupID                int              `json:"group_id"`
-	GroupInheritanceType   int              `json:"group_inheritance_type"`
 }
 
 // EnvironmentApprovalRule represents the approval rules for a protected
@@ -147,10 +146,9 @@ type ProtectRepositoryEnvironmentsOptions struct {
 // GitLab API docs:
 // https://docs.gitlab.com/ee/api/protected_environments.html#protect-a-single-environment
 type EnvironmentAccessOptions struct {
-	AccessLevel          *AccessLevelValue `url:"access_level,omitempty" json:"access_level,omitempty"`
-	UserID               *int              `url:"user_id,omitempty" json:"user_id,omitempty"`
-	GroupID              *int              `url:"group_id,omitempty" json:"group_id,omitempty"`
-	GroupInheritanceType *int              `url:"group_inheritance_type,omitempty" json:"group_inheritance_type,omitempty"`
+	AccessLevel *AccessLevelValue `url:"access_level,omitempty" json:"access_level,omitempty"`
+	UserID      *int              `url:"user_id,omitempty" json:"user_id,omitempty"`
+	GroupID     *int              `url:"group_id,omitempty" json:"group_id,omitempty"`
 }
 
 // EnvironmentApprovalRuleOptions represents the approval rules for a protected
@@ -211,12 +209,11 @@ type UpdateProtectedEnvironmentsOptions struct {
 // GitLab API docs:
 // https://docs.gitlab.com/ee/api/protected_environments.html#update-a-protected-environment
 type UpdateEnvironmentAccessOptions struct {
-	AccessLevel          *AccessLevelValue `url:"access_level,omitempty" json:"access_level,omitempty"`
-	ID                   *int              `url:"id,omitempty" json:"id,omitempty"`
-	UserID               *int              `url:"user_id,omitempty" json:"user_id,omitempty"`
-	GroupID              *int              `url:"group_id,omitempty" json:"group_id,omitempty"`
-	GroupInheritanceType *int              `url:"group_inheritance_type,omitempty" json:"group_inheritance_type,omitempty"`
-	Destroy              *bool             `url:"_destroy,omitempty" json:"_destroy,omitempty"`
+	AccessLevel *AccessLevelValue `url:"access_level,omitempty" json:"access_level,omitempty"`
+	ID          *int              `url:"id,omitempty" json:"id,omitempty"`
+	UserID      *int              `url:"user_id,omitempty" json:"user_id,omitempty"`
+	GroupID     *int              `url:"group_id,omitempty" json:"group_id,omitempty"`
+	Destroy     *bool             `url:"_destroy,omitempty" json:"_destroy,omitempty"`
 }
 
 // UpdateEnvironmentApprovalRuleOptions represents the updates to the approval
diff --git a/validate.go b/validate.go
index cb79ac8..1a0f56a 100644
--- a/validate.go
+++ b/validate.go
@@ -121,8 +121,6 @@ func (s *ValidateService) ProjectNamespaceLint(pid interface{}, opt *ProjectName
 // GitLab API docs:
 // https://docs.gitlab.com/ee/api/lint.html#validate-a-projects-ci-configuration
 type ProjectLintOptions struct {
-	ContentRef  *string `url:"content_ref,omitempty" json:"content_ref,omitempty"`
-	DryRunRef   *string `url:"dry_run_ref,omitempty" json:"dry_run_ref,omitempty"`
 	DryRun      *bool   `url:"dry_run,omitempty" json:"dry_run,omitempty"`
 	IncludeJobs *bool   `url:"include_jobs,omitempty" json:"include_jobs,omitempty"`
 	Ref         *string `url:"ref,omitempty" json:"ref,omitempty"`


Test patch:
diff --git a/draft_notes_test.go b/draft_notes_test.go
deleted file mode 100644
index 266efaa..0000000
--- a/draft_notes_test.go
+++ /dev/null
@@ -1,212 +0,0 @@
-//
-// Copyright 2021, Sander van Harmelen
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-package gitlab
-
-import (
-	"net/http"
-	"reflect"
-	"testing"
-)
-
-func TestGetDraftNote(t *testing.T) {
-	mux, client := setup(t)
-	mux.HandleFunc("/api/v4/projects/1/merge_requests/4329/draft_notes/3", func(w http.ResponseWriter, r *http.Request) {
-		testMethod(t, r, http.MethodGet)
-		mustWriteHTTPResponse(t, w, "testdata/get_draft_note.json")
-	})
-
-	note, _, err := client.DraftNotes.GetDraftNote("1", 4329, 3)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	want := &DraftNote{
-		ID:                37349978,
-		AuthorID:          10271899,
-		MergeRequestID:    291473309,
-		ResolveDiscussion: false,
-		DiscussionID:      "",
-		Note:              "Some draft note",
-		CommitID:          "",
-		LineCode:          "",
-		Position:          nil,
-	}
-
-	if !reflect.DeepEqual(note, want) {
-		t.Errorf("DraftNotes.GetDraftNote want %#v, got %#v", note, want)
-	}
-}
-
-func TestListDraftNotes(t *testing.T) {
-	mux, client := setup(t)
-	mux.HandleFunc("/api/v4/projects/1/merge_requests/4329/draft_notes", func(w http.ResponseWriter, r *http.Request) {
-		testMethod(t, r, http.MethodGet)
-		mustWriteHTTPResponse(t, w, "testdata/list_draft_notes.json")
-	})
-
-	notes, _, err := client.DraftNotes.ListDraftNotes("1", 4329, nil)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	want := []*DraftNote{
-		{
-			ID:                37349978,
-			AuthorID:          10271899,
-			MergeRequestID:    291473309,
-			ResolveDiscussion: false,
-			DiscussionID:      "",
-			Note:              "Some draft note",
-			CommitID:          "",
-			LineCode:          "",
-			Position:          nil,
-		},
-		{
-			ID:                37349979,
-			AuthorID:          10271899,
-			MergeRequestID:    291473309,
-			ResolveDiscussion: false,
-			DiscussionID:      "",
-			Note:              "Some draft note 2",
-			CommitID:          "",
-			LineCode:          "3dacf79e0d779e2baa1c700cf56510e42f55cf85_10_9",
-			Position: &NotePosition{
-				BaseSHA:      "64581c4ee41beb44d943d7801f82d9038e25e453",
-				StartSHA:     "87bffbff93bf334889780f54ae1922355661f867",
-				HeadSHA:      "2c972dbf9094c380f5f00dcd8112d2c69b24c859",
-				OldPath:      "src/some-dir/some-file.js",
-				NewPath:      "src/some-dir/some-file.js",
-				PositionType: "text",
-				NewLine:      9,
-				LineRange: &LineRange{
-					StartRange: &LinePosition{
-						LineCode: "3dacf79e0d779e2baa1c700cf56510e42f55cf85_10_9",
-						Type:     "new",
-						NewLine:  9,
-					},
-					EndRange: &LinePosition{
-						LineCode: "3dacf79e0d779e2baa1c700cf56510e42f55cf85_10_9",
-						Type:     "new",
-						NewLine:  9,
-					},
-				},
-			},
-		},
-	}
-
-	if !reflect.DeepEqual(notes, want) {
-		t.Errorf("DraftNotes.GetDraftNote want %#v, got %#v", notes, want)
-	}
-}
-
-func TestCreateDraftNote(t *testing.T) {
-	mux, client := setup(t)
-	mux.HandleFunc("/api/v4/projects/1/merge_requests/4329/draft_notes", func(w http.ResponseWriter, r *http.Request) {
-		testMethod(t, r, http.MethodPost)
-		mustWriteHTTPResponse(t, w, "testdata/create_draft_note.json")
-	})
-
-	note, _, err := client.DraftNotes.CreateDraftNote("1", 4329, &CreateDraftNoteOptions{
-		Note: Ptr("Some new draft note"),
-	})
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	want := &DraftNote{
-		ID:                37349980,
-		AuthorID:          10271899,
-		MergeRequestID:    291473309,
-		ResolveDiscussion: false,
-		DiscussionID:      "",
-		Note:              "Some new draft note",
-		CommitID:          "",
-		LineCode:          "",
-		Position:          nil,
-	}
-
-	if !reflect.DeepEqual(note, want) {
-		t.Errorf("DraftNotes.GetDraftNote want %#v, got %#v", note, want)
-	}
-}
-
-func TestUpdateDraftNote(t *testing.T) {
-	mux, client := setup(t)
-	mux.HandleFunc("/api/v4/projects/1/merge_requests/4329/draft_notes/3", func(w http.ResponseWriter, r *http.Request) {
-		testMethod(t, r, http.MethodPut)
-		mustWriteHTTPResponse(t, w, "testdata/update_draft_note.json")
-	})
-
-	note, _, err := client.DraftNotes.UpdateDraftNote("1", 4329, 3, &UpdateDraftNoteOptions{
-		Note: Ptr("Some changed draft note"),
-	})
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	want := &DraftNote{
-		ID:                37349980,
-		AuthorID:          10271899,
-		MergeRequestID:    291473309,
-		ResolveDiscussion: false,
-		DiscussionID:      "",
-		Note:              "Some changed draft note",
-		CommitID:          "",
-		LineCode:          "",
-		Position:          nil,
-	}
-
-	if !reflect.DeepEqual(note, want) {
-		t.Errorf("DraftNotes.UpdateDraftNote want %#v, got %#v", note, want)
-	}
-}
-
-func TestDeleteDraftNote(t *testing.T) {
-	mux, client := setup(t)
-	mux.HandleFunc("/api/v4/projects/1/merge_requests/4329/draft_notes/3", func(w http.ResponseWriter, r *http.Request) {
-		testMethod(t, r, http.MethodDelete)
-	})
-
-	_, err := client.DraftNotes.DeleteDraftNote("1", 4329, 3)
-	if err != nil {
-		t.Errorf("DraftNotes.DeleteDraftNote returned error: %v", err)
-	}
-}
-
-func TestPublishDraftNote(t *testing.T) {
-	mux, client := setup(t)
-	mux.HandleFunc("/api/v4/projects/1/merge_requests/4329/draft_notes/3/publish", func(w http.ResponseWriter, r *http.Request) {
-		testMethod(t, r, http.MethodPut)
-	})
-
-	_, err := client.DraftNotes.PublishDraftNote("1", 4329, 3)
-	if err != nil {
-		t.Errorf("DraftNotes.PublishDraftNote returned error: %v", err)
-	}
-}
-
-func TestPublishAllDraftNotes(t *testing.T) {
-	mux, client := setup(t)
-	mux.HandleFunc("/api/v4/projects/1/merge_requests/4329/draft_notes/bulk_publish", func(w http.ResponseWriter, r *http.Request) {
-		testMethod(t, r, http.MethodPost)
-	})
-
-	_, err := client.DraftNotes.PublishAllDraftNotes("1", 4329)
-	if err != nil {
-		t.Errorf("DraftNotes.PublishAllDraftNotes returned error: %v", err)
-	}
-}
diff --git a/group_hooks_test.go b/group_hooks_test.go
index 20083e5..cb434eb 100644
--- a/group_hooks_test.go
+++ b/group_hooks_test.go
@@ -48,9 +48,11 @@ func TestListGroupHooks(t *testing.T) {
 		"deployment_events": true,
 		"releases_events": true,
 		"subgroup_events": true,
+		"member_events": true,
 		"enable_ssl_verification": true,
 		"alert_status": "executable",
-		"created_at": "2012-10-12T17:04:47Z"
+		"created_at": "2012-10-12T17:04:47Z",
+		"resource_access_token_events": true
 	}
 ]`)
 	})
@@ -62,25 +64,27 @@ func TestListGroupHooks(t *testing.T) {
 
 	datePointer := time.Date(2012, 10, 12, 17, 4, 47, 0, time.UTC)
 	want := []*GroupHook{{
-		ID:                       1,
-		URL:                      "http://example.com/hook",
-		GroupID:                  3,
-		PushEvents:               true,
-		PushEventsBranchFilter:   "main",
-		IssuesEvents:             true,
-		ConfidentialIssuesEvents: true,
-		MergeRequestsEvents:      true,
-		TagPushEvents:            true,
-		NoteEvents:               true,
-		JobEvents:                true,
-		PipelineEvents:           true,
-		WikiPageEvents:           true,
-		DeploymentEvents:         true,
-		ReleasesEvents:           true,
-		SubGroupEvents:           true,
-		EnableSSLVerification:    true,
-		AlertStatus:              "executable",
-		CreatedAt:                &datePointer,
+		ID:                        1,
+		URL:                       "http://example.com/hook",
+		GroupID:                   3,
+		PushEvents:                true,
+		PushEventsBranchFilter:    "main",
+		IssuesEvents:              true,
+		ConfidentialIssuesEvents:  true,
+		MergeRequestsEvents:       true,
+		TagPushEvents:             true,
+		NoteEvents:                true,
+		JobEvents:                 true,
+		PipelineEvents:            true,
+		WikiPageEvents:            true,
+		DeploymentEvents:          true,
+		ReleasesEvents:            true,
+		SubGroupEvents:            true,
+		MemberEvents:              true,
+		EnableSSLVerification:     true,
+		AlertStatus:               "executable",
+		CreatedAt:                 &datePointer,
+		ResourceAccessTokenEvents: true,
 	}}
 
 	if !reflect.DeepEqual(groupHooks, want) {
@@ -111,9 +115,11 @@ func TestGetGroupHook(t *testing.T) {
 	"deployment_events": true,
 	"releases_events": true,
 	"subgroup_events": true,
+	"member_events": true,
 	"enable_ssl_verification": true,
 	"alert_status": "executable",
-	"created_at": "2012-10-12T17:04:47Z"
+	"created_at": "2012-10-12T17:04:47Z",
+	"resource_access_token_events": true
 }`)
 	})
 
@@ -124,25 +130,27 @@ func TestGetGroupHook(t *testing.T) {
 
 	datePointer := time.Date(2012, 10, 12, 17, 4, 47, 0, time.UTC)
 	want := &GroupHook{
-		ID:                       1,
-		URL:                      "http://example.com/hook",
-		GroupID:                  3,
-		PushEvents:               true,
-		PushEventsBranchFilter:   "main",
-		IssuesEvents:             true,
-		ConfidentialIssuesEvents: true,
-		MergeRequestsEvents:      true,
-		TagPushEvents:            true,
-		NoteEvents:               true,
-		JobEvents:                true,
-		PipelineEvents:           true,
-		WikiPageEvents:           true,
-		DeploymentEvents:         true,
-		ReleasesEvents:           true,
-		SubGroupEvents:           true,
-		EnableSSLVerification:    true,
-		AlertStatus:              "executable",
-		CreatedAt:                &datePointer,
+		ID:                        1,
+		URL:                       "http://example.com/hook",
+		GroupID:                   3,
+		PushEvents:                true,
+		PushEventsBranchFilter:    "main",
+		IssuesEvents:              true,
+		ConfidentialIssuesEvents:  true,
+		MergeRequestsEvents:       true,
+		TagPushEvents:             true,
+		NoteEvents:                true,
+		JobEvents:                 true,
+		PipelineEvents:            true,
+		WikiPageEvents:            true,
+		DeploymentEvents:          true,
+		ReleasesEvents:            true,
+		SubGroupEvents:            true,
+		MemberEvents:              true,
+		EnableSSLVerification:     true,
+		AlertStatus:               "executable",
+		CreatedAt:                 &datePointer,
+		ResourceAccessTokenEvents: true,
 	}
 
 	if !reflect.DeepEqual(groupHook, want) {
@@ -173,9 +181,11 @@ func TestAddGroupHook(t *testing.T) {
 	"deployment_events": true,
 	"releases_events": true,
 	"subgroup_events": true,
+	"member_events": true,
 	"enable_ssl_verification": true,
 	"created_at": "2012-10-12T17:04:47Z",
-	"custom_webhook_template": "addTestValue"
+	"custom_webhook_template": "addTestValue",
+	"resource_access_token_events": true
 }`)
 	})
 
@@ -191,26 +201,28 @@ func TestAddGroupHook(t *testing.T) {
 
 	datePointer := time.Date(2012, 10, 12, 17, 4, 47, 0, time.UTC)
 	want := &GroupHook{
-		ID:                       1,
-		URL:                      "http://example.com/hook",
-		GroupID:                  3,
-		PushEvents:               true,
-		PushEventsBranchFilter:   "main",
-		IssuesEvents:             true,
-		ConfidentialIssuesEvents: true,
-		ConfidentialNoteEvents:   false,
-		MergeRequestsEvents:      true,
-		TagPushEvents:            true,
-		NoteEvents:               true,
-		JobEvents:                true,
-		PipelineEvents:           true,
-		WikiPageEvents:           true,
-		DeploymentEvents:         true,
-		ReleasesEvents:           true,
-		SubGroupEvents:           true,
-		EnableSSLVerification:    true,
-		CreatedAt:                &datePointer,
-		CustomWebhookTemplate:    "addTestValue",
+		ID:                        1,
+		URL:                       "http://example.com/hook",
+		GroupID:                   3,
+		PushEvents:                true,
+		PushEventsBranchFilter:    "main",
+		IssuesEvents:              true,
+		ConfidentialIssuesEvents:  true,
+		ConfidentialNoteEvents:    false,
+		MergeRequestsEvents:       true,
+		TagPushEvents:             true,
+		NoteEvents:                true,
+		JobEvents:                 true,
+		PipelineEvents:            true,
+		WikiPageEvents:            true,
+		DeploymentEvents:          true,
+		ReleasesEvents:            true,
+		SubGroupEvents:            true,
+		MemberEvents:              true,
+		EnableSSLVerification:     true,
+		CreatedAt:                 &datePointer,
+		CustomWebhookTemplate:     "addTestValue",
+		ResourceAccessTokenEvents: true,
 	}
 
 	if !reflect.DeepEqual(groupHooks, want) {
@@ -241,9 +253,11 @@ func TestEditGroupHook(t *testing.T) {
 	"deployment_events": true,
 	"releases_events": true,
 	"subgroup_events": true,
+	"member_events": true,
 	"enable_ssl_verification": true,
 	"created_at": "2012-10-12T17:04:47Z",
-	"custom_webhook_template": "testValue"
+	"custom_webhook_template": "testValue",
+	"resource_access_token_events": true
 }`)
 	})
 
@@ -259,26 +273,28 @@ func TestEditGroupHook(t *testing.T) {
 
 	datePointer := time.Date(2012, 10, 12, 17, 4, 47, 0, time.UTC)
 	want := &GroupHook{
-		ID:                       1,
-		URL:                      "http://example.com/hook",
-		GroupID:                  3,
-		PushEvents:               true,
-		PushEventsBranchFilter:   "main",
-		IssuesEvents:             true,
-		ConfidentialIssuesEvents: true,
-		ConfidentialNoteEvents:   false,
-		MergeRequestsEvents:      true,
-		TagPushEvents:            true,
-		NoteEvents:               true,
-		JobEvents:                true,
-		PipelineEvents:           true,
-		WikiPageEvents:           true,
-		DeploymentEvents:         true,
-		ReleasesEvents:           true,
-		SubGroupEvents:           true,
-		EnableSSLVerification:    true,
-		CreatedAt:                &datePointer,
-		CustomWebhookTemplate:    "testValue",
+		ID:                        1,
+		URL:                       "http://example.com/hook",
+		GroupID:                   3,
+		PushEvents:                true,
+		PushEventsBranchFilter:    "main",
+		IssuesEvents:              true,
+		ConfidentialIssuesEvents:  true,
+		ConfidentialNoteEvents:    false,
+		MergeRequestsEvents:       true,
+		TagPushEvents:             true,
+		NoteEvents:                true,
+		JobEvents:                 true,
+		PipelineEvents:            true,
+		WikiPageEvents:            true,
+		DeploymentEvents:          true,
+		ReleasesEvents:            true,
+		SubGroupEvents:            true,
+		MemberEvents:              true,
+		EnableSSLVerification:     true,
+		CreatedAt:                 &datePointer,
+		CustomWebhookTemplate:     "testValue",
+		ResourceAccessTokenEvents: true,
 	}
 
 	if !reflect.DeepEqual(groupHooks, want) {
diff --git a/group_members_test.go b/group_members_test.go
index 6ee93ce..43b9dae 100644
--- a/group_members_test.go
+++ b/group_members_test.go
@@ -287,62 +287,3 @@ func TestListGroupMembersWithSAML(t *testing.T) {
 		t.Errorf("Groups.ListBillableGroupMembers returned %+v, want %+v", members[0], want[0])
 	}
 }
-
-func TestGetGroupMemberCustomRole(t *testing.T) {
-	mux, client := setup(t)
-
-	path := fmt.Sprintf("/%sgroups/1/members/2", apiVersionPath)
-	mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
-		testMethod(t, r, http.MethodGet)
-
-		// This is pulled straight from a `/group/<group_id>/members/<user_id>` call, then obfuscated.
-		fmt.Fprint(w, `
-		{
-			"id":1,
-			"username":"test",
-			"name":"testName",
-			"access_level":30,
-			"member_role":{
-				"id":1,
-				"group_id":2,
-				"name":"TestingCustomRole",
-				"description":"",
-				"base_access_level":30,
-				"admin_cicd_variables":true,
-				"admin_group_member":null,
-				"admin_merge_request":null,
-				"admin_push_rules":null,
-				"admin_terraform_state":null,
-				"admin_vulnerability":null,
-				"archive_project":null,
-				"manage_group_access_tokens":null,
-				"manage_project_access_tokens":null,
-				"read_code":null,
-				"read_dependency":null,
-				"read_vulnerability":null,
-				"remove_group":null,
-				"remove_project":null
-			}
-		}
-		`)
-	})
-
-	want := &GroupMember{
-		ID:          1,
-		Username:    "test",
-		Name:        "testName",
-		AccessLevel: AccessLevelValue(30),
-		MemberRole: &MemberRole{
-			ID:                 1,
-			GroupId:            2,
-			Name:               "TestingCustomRole",
-			Description:        "",
-			BaseAccessLevel:    AccessLevelValue(30),
-			AdminCICDVariables: true,
-		},
-	}
-	member, _, err := client.GroupMembers.GetGroupMember(1, 2)
-
-	assert.NoError(t, err)
-	assert.Equal(t, want, member)
-}
diff --git a/group_protected_environments_test.go b/group_protected_environments_test.go
index 0baff6f..2866e52 100644
--- a/group_protected_environments_test.go
+++ b/group_protected_environments_test.go
@@ -34,8 +34,7 @@ func TestGroupListProtectedEnvironments(t *testing.T) {
       "deploy_access_levels": [
         {
           "access_level": 40,
-          "access_level_description": "Maintainers",
-          "group_inheritance_type": 0
+          "access_level_description": "Maintainers"
         }
       ],
       "required_approval_count": 1,
@@ -127,8 +126,7 @@ func TestGroupGetProtectedEnvironment(t *testing.T) {
       "deploy_access_levels": [
         {
           "access_level": 30,
-          "access_level_description": "Developers + Maintainers",
-          "group_inheritance_type": 1
+          "access_level_description": "Developers + Maintainers"
         }
       ],
       "required_approval_count": 1,
@@ -152,7 +150,6 @@ func TestGroupGetProtectedEnvironment(t *testing.T) {
 			{
 				AccessLevel:            30,
 				AccessLevelDescription: "Developers + Maintainers",
-				GroupInheritanceType:   1,
 			},
 		},
 		RequiredApprovalCount: 1,
@@ -180,8 +177,7 @@ func TestGroupGetProtectedEnvironment(t *testing.T) {
       "deploy_access_levels": [
         {
           "access_level": 30,
-          "access_level_description": "Developers + Maintainers",
-          "group_inheritance_type": 1
+          "access_level_description": "Developers + Maintainers"
         }
       ]
     }`, environmentName)
@@ -193,7 +189,6 @@ func TestGroupGetProtectedEnvironment(t *testing.T) {
 			{
 				AccessLevel:            30,
 				AccessLevelDescription: "Developers + Maintainers",
-				GroupInheritanceType:   1,
 			},
 		},
 	}
@@ -216,8 +211,7 @@ func TestGroupProtectEnvironments(t *testing.T) {
       "deploy_access_levels": [
         {
           "access_level": 30,
-          "access_level_description": "Developers + Maintainers",
-          "group_inheritance_type": 0
+          "access_level_description": "Developers + Maintainers"
         }
       ],
       "required_approval_count": 2,
@@ -324,8 +318,7 @@ func TestGroupUpdateProtectedEnvironments(t *testing.T) {
         {
           "id": 42,
           "access_level": 30,
-          "access_level_description": "Developers + Maintainers",
-          "group_inheritance_type": 1
+          "access_level_description": "Developers + Maintainers"
         }
       ],
       "required_approval_count": 2,
@@ -350,7 +343,6 @@ func TestGroupUpdateProtectedEnvironments(t *testing.T) {
 				ID:                     42,
 				AccessLevel:            30,
 				AccessLevelDescription: "Developers + Maintainers",
-				GroupInheritanceType:   1,
 			},
 		},
 		RequiredApprovalCount: 2,
@@ -367,16 +359,13 @@ func TestGroupUpdateProtectedEnvironments(t *testing.T) {
 	opt := &UpdateGroupProtectedEnvironmentOptions{
 		Name: Ptr(environmentName),
 		DeployAccessLevels: &[]*UpdateGroupEnvironmentAccessOptions{
-			{
-				AccessLevel:          Ptr(AccessLevelValue(30)),
-				GroupInheritanceType: Ptr(1),
-			},
+			{AccessLevel: Ptr(AccessLevelValue(30))},
 		},
 		RequiredApprovalCount: Ptr(2),
 		ApprovalRules: &[]*UpdateGroupEnvironmentApprovalRuleOptions{
 			{
 				GroupID:                Ptr(10),
-				AccessLevel:            Ptr(AccessLevelValue(5)),
+				AccessLevel:            Ptr(AccessLevelValue(0)),
 				AccessLevelDescription: Ptr("devops"),
 			},
 		},
@@ -431,8 +420,7 @@ func TestGroupUpdateProtectedEnvironments(t *testing.T) {
         {
           "id": 42,
           "access_level": 30,
-          "access_level_description": "Developers + Maintainers",
-          "group_inheritance_type": 0
+          "access_level_description": "Developers + Maintainers"
         }
       ],
 	  "required_approval_count": 2
@@ -446,7 +434,6 @@ func TestGroupUpdateProtectedEnvironments(t *testing.T) {
 				ID:                     42,
 				AccessLevel:            30,
 				AccessLevelDescription: "Developers + Maintainers",
-				GroupInheritanceType:   0,
 			},
 		},
 		RequiredApprovalCount: 2,
@@ -456,9 +443,8 @@ func TestGroupUpdateProtectedEnvironments(t *testing.T) {
 		Name: Ptr(environmentName),
 		DeployAccessLevels: &[]*UpdateGroupEnvironmentAccessOptions{
 			{
-				ID:                   Ptr(42),
-				AccessLevel:          Ptr(AccessLevelValue(30)),
-				GroupInheritanceType: Ptr(0),
+				ID:          Ptr(42),
+				AccessLevel: Ptr(AccessLevelValue(30)),
 			},
 		},
 	}
@@ -519,7 +505,7 @@ func TestGroupUpdateProtectedEnvironments(t *testing.T) {
 			{
 				ID:                     Ptr(1),
 				GroupID:                Ptr(10),
-				AccessLevel:            Ptr(AccessLevelValue(5)),
+				AccessLevel:            Ptr(AccessLevelValue(0)),
 				AccessLevelDescription: Ptr("devops"),
 			},
 		},
diff --git a/group_serviceaccounts_test.go b/group_serviceaccounts_test.go
index b878c8e..e4793f6 100644
--- a/group_serviceaccounts_test.go
+++ b/group_serviceaccounts_test.go
@@ -22,8 +22,6 @@ import (
 	"reflect"
 	"testing"
 	"time"
-
-	"github.com/stretchr/testify/require"
 )
 
 func TestCreateServiceAccount(t *testing.T) {
@@ -74,14 +72,9 @@ func TestCreateServiceAccountPersonalAccessToken(t *testing.T) {
       	"token":"random_token"
       }`)
 	})
-
-	expireTime, err := ParseISOTime("2024-06-12")
-	require.NoError(t, err)
-
 	options := &CreateServiceAccountPersonalAccessTokenOptions{
-		Scopes:    Ptr([]string{"api"}),
-		Name:      Ptr("service_account_token"),
-		ExpiresAt: Ptr(expireTime),
+		Scopes: Ptr([]string{"api"}),
+		Name:   Ptr("service_account_token"),
 	}
 	pat, _, err := client.Groups.CreateServiceAccountPersonalAccessToken(1, 57, options)
 	if err != nil {
diff --git a/groups_test.go b/groups_test.go
index 2383ab8..d848e74 100644
--- a/groups_test.go
+++ b/groups_test.go
@@ -1,9 +1,7 @@
 package gitlab
 
 import (
-	"encoding/json"
 	"fmt"
-	"io"
 	"net/http"
 	"net/url"
 	"reflect"
@@ -181,6 +179,7 @@ func TestDeleteGroup_WithPermanentDelete(t *testing.T) {
 		PermanentlyRemove: Ptr(true),
 		FullPath:          Ptr("testPath"),
 	})
+
 	if err != nil {
 		t.Errorf("Groups.DeleteGroup returned error: %v", err)
 	}
@@ -594,115 +593,3 @@ func TestUpdateGroupWithIPRestrictionRanges(t *testing.T) {
 		t.Errorf("Groups.UpdatedGroup returned %+v, want %+v", group, want)
 	}
 }
-
-func TestGetGroupWithEmailsEnabled(t *testing.T) {
-	mux, client := setup(t)
-
-	mux.HandleFunc("/api/v4/groups/1",
-		func(w http.ResponseWriter, r *http.Request) {
-			testMethod(t, r, http.MethodGet)
-
-			// Modified from https://docs.gitlab.com/ee/api/groups.html#details-of-a-group
-			fmt.Fprint(w, `
-			{
-				"id": 1,
-				"name": "test",
-				"path": "test",
-				"emails_enabled": true,
-				"description": "Aliquid qui quis dignissimos distinctio ut commodi voluptas est.",
-				"visibility": "public",
-				"avatar_url": null,
-				"web_url": "https://gitlab.example.com/groups/test",
-				"request_access_enabled": false,
-				"repository_storage": "default",
-				"full_name": "test",
-				"full_path": "test",
-				"runners_token": "ba324ca7b1c77fc20bb9",
-				"file_template_project_id": 1,
-				"parent_id": null,
-				"enabled_git_access_protocol": "all",
-				"created_at": "2020-01-15T12:36:29.590Z",
-				"prevent_sharing_groups_outside_hierarchy": false,
-				"ip_restriction_ranges": null,
-				"math_rendering_limits_enabled": true,
-				"lock_math_rendering_limits_enabled": false
-			  }`)
-		})
-
-	group, _, err := client.Groups.GetGroup(1, &GetGroupOptions{})
-	if err != nil {
-		t.Errorf("Groups.UpdateGroup returned error: %v", err)
-	}
-
-	if !group.EmailsEnabled {
-		t.Fatalf("Failed to parse `emails_enabled`. Wanted true, got %v", group.EmailsEnabled)
-	}
-}
-
-func TestCreateGroupWithEmailsEnabled(t *testing.T) {
-	mux, client := setup(t)
-
-	mux.HandleFunc("/api/v4/groups",
-		func(w http.ResponseWriter, r *http.Request) {
-			testMethod(t, r, http.MethodPost)
-
-			body, err := io.ReadAll(r.Body)
-			if err != nil {
-				t.Fatalf("Failed to read the request body. Error: %v", err)
-			}
-
-			// unmarshal into generic JSON since we don't want to test CreateGroupOptions using itself to validate.
-			var bodyJson map[string]interface{}
-			err = json.Unmarshal(body, &bodyJson)
-			if err != nil {
-				t.Fatalf("Failed to parse the request body into JSON. Error: %v", err)
-			}
-
-			if bodyJson["emails_enabled"] != true {
-				t.Fatalf("Test failed. `emails_enabled` expected to be true, got %v", bodyJson["emails_enabled"])
-			}
-
-			// Response is tested via the "GET" test, only test the actual request here.
-			fmt.Fprint(w, `
-			{}`)
-		})
-
-	_, _, err := client.Groups.CreateGroup(&CreateGroupOptions{EmailsEnabled: Ptr(true)})
-	if err != nil {
-		t.Errorf("Groups.CreateGroup returned error: %v", err)
-	}
-}
-
-func TestUpdateGroupWithEmailsEnabled(t *testing.T) {
-	mux, client := setup(t)
-
-	mux.HandleFunc("/api/v4/groups/1",
-		func(w http.ResponseWriter, r *http.Request) {
-			testMethod(t, r, http.MethodPut)
-
-			body, err := io.ReadAll(r.Body)
-			if err != nil {
-				t.Fatalf("Failed to read the request body. Error: %v", err)
-			}
-
-			// unmarshal into generic JSON since we don't want to test UpdateGroupOptions using itself to validate.
-			var bodyJson map[string]interface{}
-			err = json.Unmarshal(body, &bodyJson)
-			if err != nil {
-				t.Fatalf("Failed to parse the request body into JSON. Error: %v", err)
-			}
-
-			if bodyJson["emails_enabled"] != true {
-				t.Fatalf("Test failed. `emails_enabled` expected to be true, got %v", bodyJson["emails_enabled"])
-			}
-
-			// Response is tested via the "GET" test, only test the actual request here.
-			fmt.Fprint(w, `
-			{}`)
-		})
-
-	_, _, err := client.Groups.UpdateGroup(1, &UpdateGroupOptions{EmailsEnabled: Ptr(true)})
-	if err != nil {
-		t.Errorf("Groups.UpdateGroup returned error: %v", err)
-	}
-}
diff --git a/packages_test.go b/packages_test.go
index 1fec5ba..375d259 100644
--- a/packages_test.go
+++ b/packages_test.go
@@ -105,13 +105,12 @@ func TestPackagesService_ListPackageFiles(t *testing.T) {
 	})
 
 	want := []*PackageFile{{
-		ID:         25,
-		PackageID:  4,
-		FileName:   "my-app-1.5-20181107.152550-1.jar",
-		Size:       2421,
-		FileMD5:    "58e6a45a629910c6ff99145a688971ac",
-		FileSHA1:   "ebd193463d3915d7e22219f52740056dfd26cbfe",
-		FileSHA256: "a903393463d3915d7e22219f52740056dfd26cbfeff321b",
+		ID:        25,
+		PackageID: 4,
+		FileName:  "my-app-1.5-20181107.152550-1.jar",
+		Size:      2421,
+		FileMD5:   "58e6a45a629910c6ff99145a688971ac",
+		FileSHA1:  "ebd193463d3915d7e22219f52740056dfd26cbfe",
 	}}
 
 	ps, resp, err := client.Packages.ListPackageFiles(3, 4, nil)
diff --git a/protected_environments_test.go b/protected_environments_test.go
index a973338..dca6d9d 100644
--- a/protected_environments_test.go
+++ b/protected_environments_test.go
@@ -34,8 +34,7 @@ func TestListProtectedEnvironments(t *testing.T) {
       "deploy_access_levels": [
         {
           "access_level": 40,
-          "access_level_description": "Maintainers",
-          "group_inheritance_type": 1
+          "access_level_description": "Maintainers"
         }
       ],
       "required_approval_count": 1,
@@ -77,7 +76,6 @@ func TestListProtectedEnvironments(t *testing.T) {
 				{
 					AccessLevel:            40,
 					AccessLevelDescription: "Maintainers",
-					GroupInheritanceType:   1,
 				},
 			},
 			RequiredApprovalCount: 1,
@@ -211,8 +209,7 @@ func TestProtectRepositoryEnvironments(t *testing.T) {
       "deploy_access_levels": [
         {
           "access_level": 30,
-          "access_level_description": "Developers + Maintainers",
-          "group_inheritance_type": 1
+          "access_level_description": "Developers + Maintainers"
         }
       ],
       "required_approval_count": 2,
@@ -236,7 +233,6 @@ func TestProtectRepositoryEnvironments(t *testing.T) {
 			{
 				AccessLevel:            30,
 				AccessLevelDescription: "Developers + Maintainers",
-				GroupInheritanceType:   1,
 			},
 		},
 		RequiredApprovalCount: 2,
@@ -318,8 +314,7 @@ func TestUpdateProtectedEnvironments(t *testing.T) {
         {
           "id": 42,
           "access_level": 30,
-          "access_level_description": "Developers + Maintainers",
-          "group_inheritance_type": 1
+          "access_level_description": "Developers + Maintainers"
         }
       ],
       "required_approval_count": 2,
@@ -344,7 +339,6 @@ func TestUpdateProtectedEnvironments(t *testing.T) {
 				ID:                     42,
 				AccessLevel:            30,
 				AccessLevelDescription: "Developers + Maintainers",
-				GroupInheritanceType:   1,
 			},
 		},
 		RequiredApprovalCount: 2,
@@ -361,10 +355,7 @@ func TestUpdateProtectedEnvironments(t *testing.T) {
 	opt := &UpdateProtectedEnvironmentsOptions{
 		Name: Ptr(environmentName),
 		DeployAccessLevels: &[]*UpdateEnvironmentAccessOptions{
-			{
-				AccessLevel:          Ptr(AccessLevelValue(30)),
-				GroupInheritanceType: Ptr(1),
-			},
+			{AccessLevel: Ptr(AccessLevelValue(30))},
 		},
 		RequiredApprovalCount: Ptr(2),
 		ApprovalRules: &[]*UpdateEnvironmentApprovalRuleOptions{
@@ -389,8 +380,7 @@ func TestUpdateProtectedEnvironments(t *testing.T) {
         {
           "id": 42,
           "access_level": 30,
-          "access_level_description": "Developers + Maintainers",
-          "group_inheritance_type": 1
+          "access_level_description": "Developers + Maintainers"
         }
       ]
     }`, environmentName)
@@ -403,7 +393,6 @@ func TestUpdateProtectedEnvironments(t *testing.T) {
 				ID:                     42,
 				AccessLevel:            30,
 				AccessLevelDescription: "Developers + Maintainers",
-				GroupInheritanceType:   1,
 			},
 		},
 	}
@@ -427,8 +416,7 @@ func TestUpdateProtectedEnvironments(t *testing.T) {
         {
           "id": 42,
           "access_level": 30,
-          "access_level_description": "Developers + Maintainers",
-          "group_inheritance_type": 0
+          "access_level_description": "Developers + Maintainers"
         }
       ],
 	  "required_approval_count": 2
diff --git a/testdata/create_draft_note.json b/testdata/create_draft_note.json
deleted file mode 100644
index bc0dc68..0000000
--- a/testdata/create_draft_note.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-  "id": 37349980,
-  "author_id": 10271899,
-  "merge_request_id": 291473309,
-  "resolve_discussion": false,
-  "discussion_id": null,
-  "note": "Some new draft note",
-  "commit_id": null,
-  "position": null,
-  "line_code": null
-}
diff --git a/testdata/get_draft_note.json b/testdata/get_draft_note.json
deleted file mode 100644
index a1e9cd4..0000000
--- a/testdata/get_draft_note.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-  "id": 37349978,
-  "author_id": 10271899,
-  "merge_request_id": 291473309,
-  "resolve_discussion": false,
-  "discussion_id": null,
-  "note": "Some draft note",
-  "commit_id": null,
-  "position": null,
-  "line_code": null
-}
diff --git a/testdata/list_draft_notes.json b/testdata/list_draft_notes.json
deleted file mode 100644
index 15e235b..0000000
--- a/testdata/list_draft_notes.json
+++ /dev/null
@@ -1,47 +0,0 @@
-[
-  {
-    "id": 37349978,
-    "author_id": 10271899,
-    "merge_request_id": 291473309,
-    "resolve_discussion": false,
-    "discussion_id": null,
-    "note": "Some draft note",
-    "commit_id": null,
-    "position": null,
-    "line_code": null
-  },
-  {
-    "id": 37349979,
-    "author_id": 10271899,
-    "merge_request_id": 291473309,
-    "resolve_discussion": false,
-    "discussion_id": null,
-    "note": "Some draft note 2",
-    "commit_id": null,
-    "line_code": "3dacf79e0d779e2baa1c700cf56510e42f55cf85_10_9",
-    "position": {
-      "base_sha": "64581c4ee41beb44d943d7801f82d9038e25e453",
-      "start_sha": "87bffbff93bf334889780f54ae1922355661f867",
-      "head_sha": "2c972dbf9094c380f5f00dcd8112d2c69b24c859",
-      "old_path": "src/some-dir/some-file.js",
-      "new_path": "src/some-dir/some-file.js",
-      "position_type": "text",
-      "old_line": null,
-      "new_line": 9,
-      "line_range": {
-        "start": {
-          "line_code": "3dacf79e0d779e2baa1c700cf56510e42f55cf85_10_9",
-          "type": "new",
-          "old_line": null,
-          "new_line": 9
-        },
-        "end": {
-          "line_code": "3dacf79e0d779e2baa1c700cf56510e42f55cf85_10_9",
-          "type": "new",
-          "old_line": null,
-          "new_line": 9
-        }
-      }
-    }
-  }
-]
diff --git a/testdata/update_draft_note.json b/testdata/update_draft_note.json
deleted file mode 100644
index 98cea1a..0000000
--- a/testdata/update_draft_note.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-  "id": 37349980,
-  "author_id": 10271899,
-  "merge_request_id": 291473309,
-  "resolve_discussion": false,
-  "discussion_id": null,
-  "note": "Some changed draft note",
-  "commit_id": null,
-  "position": null,
-  "line_code": null
-}
diff --git a/validate_test.go b/validate_test.go
index 20171e2..ab4bfc3 100644
--- a/validate_test.go
+++ b/validate_test.go
@@ -223,54 +223,3 @@ func TestValidateProjectNamespace(t *testing.T) {
 		})
 	}
 }
-
-func TestValidateProjectLint(t *testing.T) {
-	testCases := []struct {
-		description string
-		request     *ProjectLintOptions
-		response    string
-		want        *ProjectLintResult
-	}{
-		{
-			description: "valid",
-			request: &ProjectLintOptions{
-				DryRun:      Ptr(false),
-				IncludeJobs: Ptr(true),
-				ContentRef:  Ptr("foo"),
-			},
-			response: `{
-				"valid": true,
-				"errors": [],
-				"warnings": [],
-				"merged_yaml": 	"---\n:build:\n  :script:\n  - echo build"
-			}`,
-			want: &ProjectLintResult{
-				Valid:      true,
-				Warnings:   []string{},
-				Errors:     []string{},
-				MergedYaml: "---\n:build:\n  :script:\n  - echo build",
-			},
-		},
-	}
-
-	for _, tc := range testCases {
-		t.Run(tc.description, func(t *testing.T) {
-			mux, client := setup(t)
-
-			mux.HandleFunc("/api/v4/projects/1/ci/lint", func(w http.ResponseWriter, r *http.Request) {
-				testMethod(t, r, http.MethodGet)
-				fmt.Fprint(w, tc.response)
-			})
-
-			got, _, err := client.Validate.ProjectLint(1, tc.request)
-			if err != nil {
-				t.Errorf("Validate returned error: %v", err)
-			}
-
-			want := tc.want
-			if !reflect.DeepEqual(got, want) {
-				t.Errorf("Validate returned \ngot:\n%v\nwant:\n%v", Stringify(got), Stringify(want))
-			}
-		})
-	}
-}