Repository: xanzy/go-gitlab
Pull request #1810 (2023-10-02 05:48:21)

Add Resource Iteration Events Support
Add support for issue iteration events.
Route: `/projects/:id/issues/:issue_iid/resource_iteration_events`
Documentation: https://docs.gitlab.com/ee/api/resource_iteration_events.html

## Changes
* Added `ResourceIterationEventsService`
    * Added `GetIssueIterationEvent` and `ListIssueIterationEvents` functions


Patch:
diff --git a/gitlab.go b/gitlab.go
index 6586288..aba0eba 100644
--- a/gitlab.go
+++ b/gitlab.go
@@ -201,6 +201,7 @@ type Client struct {
 	Repositories                 *RepositoriesService
 	RepositoryFiles              *RepositoryFilesService
 	RepositorySubmodules         *RepositorySubmodulesService
+	ResourceIterationEvents      *ResourceIterationEventsService
 	ResourceLabelEvents          *ResourceLabelEventsService
 	ResourceMilestoneEvents      *ResourceMilestoneEventsService
 	ResourceStateEvents          *ResourceStateEventsService
@@ -424,6 +425,7 @@ func newClient(options ...ClientOptionFunc) (*Client, error) {
 	c.Repositories = &RepositoriesService{client: c}
 	c.RepositoryFiles = &RepositoryFilesService{client: c}
 	c.RepositorySubmodules = &RepositorySubmodulesService{client: c}
+	c.ResourceIterationEvents = &ResourceIterationEventsService{client: c}
 	c.ResourceLabelEvents = &ResourceLabelEventsService{client: c}
 	c.ResourceMilestoneEvents = &ResourceMilestoneEventsService{client: c}
 	c.ResourceStateEvents = &ResourceStateEventsService{client: c}
diff --git a/resource_iteration_events.go b/resource_iteration_events.go
new file mode 100644
index 0000000..7ad354a
--- /dev/null
+++ b/resource_iteration_events.go
@@ -0,0 +1,122 @@
+//
+// Copyright 2023, Hakki Ceylan, Yavuz Turk
+//
+// 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"
+	"time"
+)
+
+// ResourceIterationEventsService handles communication with the event related
+// methods of the GitLab API.
+//
+// GitLab API docs: https://docs.gitlab.com/ee/api/resource_iteration_events.html
+type ResourceIterationEventsService struct {
+	client *Client
+}
+
+// IterationEvent represents a resource iteration event.
+//
+// GitLab API docs: https://docs.gitlab.com/ee/api/resource_iteration_events.html
+type IterationEvent struct {
+	ID           int        `json:"id"`
+	User         *BasicUser `json:"user"`
+	CreatedAt    *time.Time `json:"created_at"`
+	ResourceType string     `json:"resource_type"`
+	ResourceID   int        `json:"resource_id"`
+	Iteration    *Iteration `json:"iteration"`
+	Action       string     `json:"action"`
+}
+
+// Iteration represents a project issue iteration.
+//
+// GitLab API docs: https://docs.gitlab.com/ee/api/resource_iteration_events.html
+type Iteration struct {
+	ID          int        `json:"id"`
+	IID         int        `json:"iid"`
+	Sequence    int        `json:"sequence"`
+	GroupId     int        `json:"group_id"`
+	Title       string     `json:"title"`
+	Description string     `json:"description"`
+	State       int        `json:"state"`
+	CreatedAt   *time.Time `json:"created_at"`
+	UpdatedAt   *time.Time `json:"updated_at"`
+	DueDate     *ISOTime   `json:"due_date"`
+	StartDate   *ISOTime   `json:"start_date"`
+	WebURL      string     `json:"web_url"`
+}
+
+// ListIterationEventsOptions represents the options for all resource state
+// events list methods.
+//
+// GitLab API docs:
+// https://docs.gitlab.com/ee/api/resource_iteration_events.html#list-project-issue-iteration-events
+type ListIterationEventsOptions struct {
+	ListOptions
+}
+
+// ListIssueIterationEvents retrieves resource iteration events for the
+// specified project and issue.
+//
+// GitLab API docs:
+// https://docs.gitlab.com/ee/api/resource_iteration_events.html#list-project-issue-iteration-events
+func (s *ResourceIterationEventsService) ListIssueIterationEvents(pid interface{}, issue int, opt *ListIterationEventsOptions, options ...RequestOptionFunc) ([]*IterationEvent, *Response, error) {
+	project, err := parseID(pid)
+	if err != nil {
+		return nil, nil, err
+	}
+	u := fmt.Sprintf("projects/%s/issues/%d/resource_iteration_events", PathEscape(project), issue)
+
+	req, err := s.client.NewRequest(http.MethodGet, u, opt, options)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	var ies []*IterationEvent
+	resp, err := s.client.Do(req, &ies)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return ies, resp, nil
+}
+
+// GetIssueIterationEvent gets a single issue iteration event.
+//
+// GitLab API docs:
+// https://docs.gitlab.com/ee/api/resource_iteration_events.html#get-single-issue-iteration-event
+func (s *ResourceIterationEventsService) GetIssueIterationEvent(pid interface{}, issue int, event int, options ...RequestOptionFunc) (*IterationEvent, *Response, error) {
+	project, err := parseID(pid)
+	if err != nil {
+		return nil, nil, err
+	}
+	u := fmt.Sprintf("projects/%s/issues/%d/resource_iteration_events/%d", PathEscape(project), issue, event)
+
+	req, err := s.client.NewRequest(http.MethodGet, u, nil, options)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	ie := new(IterationEvent)
+	resp, err := s.client.Do(req, ie)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return ie, resp, nil
+}


Test patch:
diff --git a/resource_iteration_events_test.go b/resource_iteration_events_test.go
new file mode 100644
index 0000000..f4c707b
--- /dev/null
+++ b/resource_iteration_events_test.go
@@ -0,0 +1,183 @@
+// Copyright 2023, Hakki Ceylan, Yavuz Turk
+//
+// 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"
+	"testing"
+	"time"
+
+	"github.com/stretchr/testify/require"
+)
+
+func TestListIssueIterationEventsService_ListIssueIterationEvents(t *testing.T) {
+	mux, client := setup(t)
+
+	mux.HandleFunc("/api/v4/projects/5/issues/11/resource_iteration_events", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, http.MethodGet)
+		fmt.Fprintf(w, `[
+			{
+			    "id": 142,
+			    "user": {
+			        "id": 1,
+			        "username": "root",
+			        "name": "Administrator",
+			        "state": "active",
+			        "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
+			        "web_url": "https://gitlab.example.com/root"
+			    },
+			    "created_at": "2023-09-22T06:51:04.801Z",
+			    "resource_type": "Issue",
+			    "resource_id": 11,
+			    "iteration": {
+			        "id": 133,
+			        "iid": 1,
+			        "sequence": 1,
+			        "group_id": 153,
+			        "title": "Iteration 1",
+			        "description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
+			        "state": 1,
+			        "created_at": "2023-07-15T00:05:06.509Z",
+			        "updated_at": "2023-09-24T00:05:10.476Z",
+			        "start_date": "2023-09-17",
+			        "due_date": "2023-09-23",
+			        "web_url": "https://gitlab.example.com/groups/project/-/iterations/1"
+			    },
+			    "action": "add"
+			}
+		]`)
+	})
+
+	opt := &ListIterationEventsOptions{ListOptions{Page: 1, PerPage: 10}}
+
+	mes, _, err := client.ResourceIterationEvents.ListIssueIterationEvents(5, 11, opt)
+	require.NoError(t, err)
+
+	startDateISOTime, err := ParseISOTime("2023-09-17")
+	require.NoError(t, err)
+
+	dueDateISOTime, err := ParseISOTime("2023-09-23")
+	require.NoError(t, err)
+
+	want := []*IterationEvent{{
+		ID: 142,
+		User: &BasicUser{
+			ID:        1,
+			Username:  "root",
+			Name:      "Administrator",
+			State:     "active",
+			AvatarURL: "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
+			WebURL:    "https://gitlab.example.com/root",
+		},
+		ResourceType: "Issue",
+		ResourceID:   11,
+		CreatedAt:    Time(time.Date(2023, time.September, 22, 0o6, 51, 0o4, 801000000, time.UTC)),
+		Iteration: &Iteration{
+			ID:          133,
+			IID:         1,
+			Sequence:    1,
+			GroupId:     153,
+			Title:       "Iteration 1",
+			Description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
+			State:       1,
+			CreatedAt:   Time(time.Date(2023, time.July, 15, 0o0, 0o5, 0o6, 509000000, time.UTC)),
+			UpdatedAt:   Time(time.Date(2023, time.September, 24, 0o0, 0o5, 10, 476000000, time.UTC)),
+			StartDate:   &startDateISOTime,
+			DueDate:     &dueDateISOTime,
+			WebURL:      "https://gitlab.example.com/groups/project/-/iterations/1",
+		},
+		Action: "add",
+	}}
+	require.Equal(t, want, mes)
+}
+
+func TestListIssueIterationEventsService_GetIssueIterationEvent(t *testing.T) {
+	mux, client := setup(t)
+
+	mux.HandleFunc("/api/v4/projects/5/issues/11/resource_iteration_events/143", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, http.MethodGet)
+		fmt.Fprintf(w, `
+			{
+			    "id": 143,
+			    "user": {
+			        "id": 1,
+			        "username": "root",
+			        "name": "Administrator",
+			        "state": "active",
+			        "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
+			        "web_url": "https://gitlab.example.com/root"
+			    },
+			    "created_at": "2023-09-22T06:51:04.801Z",
+			    "resource_type": "Issue",
+			    "resource_id": 11,
+			    "iteration": {
+			        "id": 133,
+			        "iid": 1,
+			        "sequence": 1,
+			        "group_id": 153,
+			        "title": "Iteration 1",
+			        "description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
+			        "state": 1,
+			        "created_at": "2023-07-15T00:05:06.509Z",
+			        "updated_at": "2023-09-24T00:05:10.476Z",
+			        "start_date": "2023-09-17",
+			        "due_date": "2023-09-23",
+			        "web_url": "https://gitlab.example.com/groups/project/-/iterations/2"
+			    },
+			    "action": "add"
+			}`,
+		)
+	})
+
+	me, _, err := client.ResourceIterationEvents.GetIssueIterationEvent(5, 11, 143)
+	require.NoError(t, err)
+
+	startDateISOTime, err := ParseISOTime("2023-09-17")
+	require.NoError(t, err)
+
+	dueDateISOTime, err := ParseISOTime("2023-09-23")
+	require.NoError(t, err)
+
+	want := &IterationEvent{
+		ID: 143,
+		User: &BasicUser{
+			ID:        1,
+			Username:  "root",
+			Name:      "Administrator",
+			State:     "active",
+			AvatarURL: "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
+			WebURL:    "https://gitlab.example.com/root",
+		},
+		ResourceType: "Issue",
+		ResourceID:   11,
+		CreatedAt:    Time(time.Date(2023, time.September, 22, 0o6, 51, 0o4, 801000000, time.UTC)),
+		Iteration: &Iteration{
+			ID:          133,
+			IID:         1,
+			Sequence:    1,
+			GroupId:     153,
+			Title:       "Iteration 1",
+			Description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
+			State:       1,
+			CreatedAt:   Time(time.Date(2023, time.July, 15, 0o0, 0o5, 0o6, 509000000, time.UTC)),
+			UpdatedAt:   Time(time.Date(2023, time.September, 24, 0o0, 0o5, 10, 476000000, time.UTC)),
+			StartDate:   &startDateISOTime,
+			DueDate:     &dueDateISOTime,
+			WebURL:      "https://gitlab.example.com/groups/project/-/iterations/2",
+		},
+		Action: "add",
+	}
+	require.Equal(t, want, me)
+}