Repository: xanzy/go-gitlab
Pull request #1154 (2021-05-26 06:42:26)

Add packages within group and package status
Packages within group introduced in Gitlab 12.5.
Package status introduced in Gitlab 13.9.

https://docs.gitlab.com/ee/api/packages.html

Bouwdie: @svanharmelen lgtm

Patch:
diff --git a/gitlab.go b/gitlab.go
index 697e21d..aaf434b 100644
--- a/gitlab.go
+++ b/gitlab.go
@@ -132,7 +132,6 @@ type Client struct {
 	GroupCluster          *GroupClustersService
 	GroupImportExport     *GroupImportExportService
 	GroupIssueBoards      *GroupIssueBoardsService
-	GroupIterations       *GroupIterationsService
 	GroupLabels           *GroupLabelsService
 	GroupMembers          *GroupMembersService
 	GroupMilestones       *GroupMilestonesService
@@ -169,7 +168,6 @@ type Client struct {
 	ProjectAccessTokens   *ProjectAccessTokensService
 	ProjectCluster        *ProjectClustersService
 	ProjectImportExport   *ProjectImportExportService
-	ProjectIterations     *ProjectIterationsService
 	ProjectMembers        *ProjectMembersService
 	ProjectMirrors        *ProjectMirrorService
 	ProjectSnippets       *ProjectSnippetsService
@@ -329,7 +327,6 @@ func newClient(options ...ClientOptionFunc) (*Client, error) {
 	c.GroupCluster = &GroupClustersService{client: c}
 	c.GroupImportExport = &GroupImportExportService{client: c}
 	c.GroupIssueBoards = &GroupIssueBoardsService{client: c}
-	c.GroupIterations = &GroupIterationsService{client: c}
 	c.GroupLabels = &GroupLabelsService{client: c}
 	c.GroupMembers = &GroupMembersService{client: c}
 	c.GroupMilestones = &GroupMilestonesService{client: c}
@@ -366,7 +363,6 @@ func newClient(options ...ClientOptionFunc) (*Client, error) {
 	c.ProjectAccessTokens = &ProjectAccessTokensService{client: c}
 	c.ProjectCluster = &ProjectClustersService{client: c}
 	c.ProjectImportExport = &ProjectImportExportService{client: c}
-	c.ProjectIterations = &ProjectIterationsService{client: c}
 	c.ProjectMembers = &ProjectMembersService{client: c}
 	c.ProjectMirrors = &ProjectMirrorService{client: c}
 	c.ProjectSnippets = &ProjectSnippetsService{client: c}
diff --git a/group_iterations.go b/group_iterations.go
deleted file mode 100644
index a642091..0000000
--- a/group_iterations.go
+++ /dev/null
@@ -1,90 +0,0 @@
-//
-// Copyright 2022, Daniel Steinke
-//
-// 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"
-)
-
-// IterationsAPI handles communication with the iterations related methods
-// of the GitLab API
-//
-// GitLab API docs: https://docs.gitlab.com/ee/api/group_iterations.html
-type GroupIterationsService struct {
-	client *Client
-}
-
-// GroupInteration represents a GitLab iteration.
-//
-// GitLab API docs: https://docs.gitlab.com/ee/api/group_iterations.html
-type GroupIteration 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"`
-}
-
-func (i GroupIteration) String() string {
-	return Stringify(i)
-}
-
-// ListGroupIterationsOptions contains the available ListGroupIterations()
-// options
-//
-// GitLab API docs:
-// https://docs.gitlab.com/ee/api/group_iterations.html#list-group-iterations
-type ListGroupIterationsOptions struct {
-	ListOptions
-	State            *string `url:"state,omitempty" json:"state,omitempty"`
-	Search           *string `url:"search,omitempty" json:"search,omitempty"`
-	IncludeAncestors *bool   `url:"include_ancestors,omitempty" json:"include_ancestors,omitempty"`
-}
-
-// ListGroupIterations returns a list of group iterations.
-//
-// GitLab API docs:
-// https://docs.gitlab.com/ee/api/group_iterations.html#list-group-iterations
-func (s *GroupIterationsService) ListGroupIterations(gid interface{}, opt *ListGroupIterationsOptions, options ...RequestOptionFunc) ([]*GroupIteration, *Response, error) {
-	group, err := parseID(gid)
-	if err != nil {
-		return nil, nil, err
-	}
-	u := fmt.Sprintf("groups/%s/iterations", PathEscape(group))
-
-	req, err := s.client.NewRequest(http.MethodGet, u, opt, options)
-	if err != nil {
-		return nil, nil, err
-	}
-
-	var gis []*GroupIteration
-	resp, err := s.client.Do(req, &gis)
-	if err != nil {
-		return nil, nil, err
-	}
-
-	return gis, resp, err
-}
diff --git a/packages.go b/packages.go
index cb70ec7..37fe0e0 100644
--- a/packages.go
+++ b/packages.go
@@ -30,7 +30,7 @@ type PackagesService struct {
 	client *Client
 }
 
-// Package represents a GitLab single package.
+// Package represents a GitLab package.
 //
 // GitLab API docs: https://docs.gitlab.com/ee/api/packages.html
 type Package struct {
@@ -38,14 +38,29 @@ type Package struct {
 	Name        string        `json:"name"`
 	Version     string        `json:"version"`
 	PackageType string        `json:"package_type"`
+	Status      string        `json:"status"`
 	Links       *PackageLinks `json:"_links"`
 	CreatedAt   *time.Time    `json:"created_at"`
+	Tags        []string      `json:"tags"`
 }
 
 func (s Package) String() string {
 	return Stringify(s)
 }
 
+// GroupPackage represents a GitLab group package.
+//
+// GitLab API docs: https://docs.gitlab.com/ee/api/packages.html
+type GroupPackage struct {
+	Package
+	ProjectID   int    `json:"project_id"`
+	ProjectPath string `json:"project_path"`
+}
+
+func (s GroupPackage) String() string {
+	return Stringify(s)
+}
+
 // PackageLinks holds links for itself and deleting.
 type PackageLinks struct {
 	WebPath       string `json:"web_path"`
@@ -74,7 +89,8 @@ func (s PackageFile) String() string {
 	return Stringify(s)
 }
 
-// ListProjectPackagesOptions are the parameters available in a ListProjectPackages() Operation.
+// ListProjectPackagesOptions represents the available ListProjectPackages()
+// options.
 //
 // GitLab API docs:
 // https://docs.gitlab.com/ee/api/packages.html#within-a-project
@@ -85,6 +101,7 @@ type ListProjectPackagesOptions struct {
 	PackageType        *string `url:"package_type,omitempty" json:"package_type,omitempty"`
 	PackageName        *string `url:"package_name,omitempty" json:"package_name,omitempty"`
 	IncludeVersionless *bool   `url:"include_versionless,omitempty" json:"include_versionless,omitempty"`
+	Status             *string `url:"status,omitempty" json:"status,omitempty"`
 }
 
 // ListProjectPackages gets a list of packages in a project.
@@ -112,8 +129,49 @@ func (s *PackagesService) ListProjectPackages(pid interface{}, opt *ListProjectP
 	return ps, resp, err
 }
 
-// ListPackageFilesOptions represents the available
-// ListPackageFiles() options.
+// ListGroupPackagesOptions represents the available ListGroupPackages()
+// options.
+//
+// GitLab API docs:
+// https://docs.gitlab.com/ee/api/packages.html#within-a-group
+type ListGroupPackagesOptions struct {
+	ListOptions
+	ExcludeSubgroups   *bool   `url:"exclude_subgroups,omitempty" json:"exclude_subgroups,omitempty"`
+	OrderBy            *string `url:"order_by,omitempty" json:"order_by,omitempty"`
+	Sort               *string `url:"sort,omitempty" json:"sort,omitempty"`
+	PackageType        *string `url:"package_type,omitempty" json:"package_type,omitempty"`
+	PackageName        *string `url:"package_name,omitempty" json:"package_name,omitempty"`
+	IncludeVersionless *bool   `url:"include_versionless,omitempty" json:"include_versionless,omitempty"`
+	Status             *string `url:"status,omitempty" json:"status,omitempty"`
+}
+
+// ListGroupPackages gets a list of packages in a group.
+//
+// GitLab API docs:
+// https://docs.gitlab.com/ee/api/packages.html#within-a-group
+func (s *PackagesService) ListGroupPackages(gid interface{}, opt *ListGroupPackagesOptions, options ...RequestOptionFunc) ([]*GroupPackage, *Response, error) {
+	group, err := parseID(gid)
+	if err != nil {
+		return nil, nil, err
+	}
+	u := fmt.Sprintf("groups/%s/packages", PathEscape(group))
+
+	req, err := s.client.NewRequest(http.MethodGet, u, opt, options)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	var ps []*GroupPackage
+	resp, err := s.client.Do(req, &ps)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return ps, resp, err
+}
+
+// ListPackageFilesOptions represents the available ListPackageFiles()
+// options.
 //
 // GitLab API docs:
 // https://docs.gitlab.com/ee/api/packages.html#list-package-files
diff --git a/project_iterations.go b/project_iterations.go
deleted file mode 100644
index 78583ef..0000000
--- a/project_iterations.go
+++ /dev/null
@@ -1,90 +0,0 @@
-//
-// Copyright 2022, Daniel Steinke
-//
-// 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"
-)
-
-// IterationsAPI handles communication with the project iterations related
-// methods of the GitLab API
-//
-// GitLab API docs: https://docs.gitlab.com/ee/api/iterations.html
-type ProjectIterationsService struct {
-	client *Client
-}
-
-// ProjectIteration represents a GitLab project iteration.
-//
-// GitLab API docs: https://docs.gitlab.com/ee/api/iterations.html
-type ProjectIteration 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"`
-}
-
-func (i ProjectIteration) String() string {
-	return Stringify(i)
-}
-
-// ListProjectIterationsOptions contains the available ListProjectIterations()
-// options
-//
-// GitLab API docs:
-// https://docs.gitlab.com/ee/api/group_iterations.html#list-project-iterations
-type ListProjectIterationsOptions struct {
-	ListOptions
-	State            *string `url:"state,omitempty" json:"state,omitempty"`
-	Search           *string `url:"search,omitempty" json:"search,omitempty"`
-	IncludeAncestors *bool   `url:"include_ancestors,omitempty" json:"include_ancestors,omitempty"`
-}
-
-// ListProjectIterations returns a list of projects iterations.
-//
-// GitLab API docs:
-// https://docs.gitlab.com/ee/api/group_iterations.html#list-project-iterations
-func (i *ProjectIterationsService) ListProjectIterations(pid interface{}, opt *ListProjectIterationsOptions, options ...RequestOptionFunc) ([]*ProjectIteration, *Response, error) {
-	project, err := parseID(pid)
-	if err != nil {
-		return nil, nil, err
-	}
-	u := fmt.Sprintf("projects/%s/iterations", PathEscape(project))
-
-	req, err := i.client.NewRequest(http.MethodGet, u, opt, options)
-	if err != nil {
-		return nil, nil, err
-	}
-
-	var pis []*ProjectIteration
-	resp, err := i.client.Do(req, &pis)
-	if err != nil {
-		return nil, resp, err
-	}
-
-	return pis, resp, err
-}


Test patch:
diff --git a/group_iterations_test.go b/group_iterations_test.go
deleted file mode 100644
index 4d2030f..0000000
--- a/group_iterations_test.go
+++ /dev/null
@@ -1,49 +0,0 @@
-package gitlab
-
-import (
-	"fmt"
-	"net/http"
-	"reflect"
-	"testing"
-)
-
-func TestListGroupIterations(t *testing.T) {
-	mux, server, client := setup(t)
-	defer teardown(server)
-
-	mux.HandleFunc("/api/v4/groups/5/iterations",
-		func(w http.ResponseWriter, r *http.Request) {
-			testMethod(t, r, http.MethodGet)
-			fmt.Fprintf(w, `[
-        {
-          "id": 53,
-          "iid": 13,
-          "sequence": 1,
-          "group_id": 5,
-          "title": "Iteration II",
-          "description": "Ipsum Lorem ipsum",
-          "state": 2,
-          "web_url": "http://gitlab.example.com/groups/my-group/-/iterations/13"
-        }
-      ]`)
-		})
-
-	iterations, _, err := client.GroupIterations.ListGroupIterations(5, &ListGroupIterationsOptions{})
-	if err != nil {
-		t.Errorf("GroupIterations.ListGroupIterations returned error: %v", err)
-	}
-
-	want := []*GroupIteration{{
-		ID:          53,
-		IID:         13,
-		Sequence:    1,
-		GroupID:     5,
-		Title:       "Iteration II",
-		Description: "Ipsum Lorem ipsum",
-		State:       2,
-		WebURL:      "http://gitlab.example.com/groups/my-group/-/iterations/13",
-	}}
-	if !reflect.DeepEqual(want, iterations) {
-		t.Errorf("GroupIterations.ListGroupIterations returned %+v, want %+v", iterations, want)
-	}
-}
diff --git a/packages_test.go b/packages_test.go
index 207b765..cefef64 100644
--- a/packages_test.go
+++ b/packages_test.go
@@ -41,6 +41,7 @@ func TestPackagesService_ListProjectPackages(t *testing.T) {
 			WebPath:       "/foo/bar/-/packages/3",
 			DeleteAPIPath: "https://gitlab.example.com/api/v4/projects/1/packages/3",
 		},
+		Tags: []string{},
 	}}
 
 	ps, resp, err := client.Packages.ListProjectPackages(3, nil)
diff --git a/project_iterations_test.go b/project_iterations_test.go
deleted file mode 100644
index ca304c6..0000000
--- a/project_iterations_test.go
+++ /dev/null
@@ -1,49 +0,0 @@
-package gitlab
-
-import (
-	"fmt"
-	"net/http"
-	"reflect"
-	"testing"
-)
-
-func TestListProjectIterations(t *testing.T) {
-	mux, server, client := setup(t)
-	defer teardown(server)
-
-	mux.HandleFunc("/api/v4/projects/42/iterations",
-		func(w http.ResponseWriter, r *http.Request) {
-			testMethod(t, r, http.MethodGet)
-			fmt.Fprintf(w, `[
-        {
-          "id": 53,
-          "iid": 13,
-          "sequence": 1,
-          "group_id": 5,
-          "title": "Iteration II",
-          "description": "Ipsum Lorem ipsum",
-          "state": 2,
-          "web_url": "http://gitlab.example.com/groups/my-group/-/iterations/13"
-        }
-      ]`)
-		})
-
-	iterations, _, err := client.ProjectIterations.ListProjectIterations(42, &ListProjectIterationsOptions{})
-	if err != nil {
-		t.Errorf("GroupIterations.ListGroupIterations returned error: %v", err)
-	}
-
-	want := []*ProjectIteration{{
-		ID:          53,
-		IID:         13,
-		Sequence:    1,
-		GroupID:     5,
-		Title:       "Iteration II",
-		Description: "Ipsum Lorem ipsum",
-		State:       2,
-		WebURL:      "http://gitlab.example.com/groups/my-group/-/iterations/13",
-	}}
-	if !reflect.DeepEqual(want, iterations) {
-		t.Errorf("ProjectIterations.ListProjectIterations returned %+v, want %+v", iterations, want)
-	}
-}
diff --git a/testdata/list_group_iterations.json b/testdata/list_group_iterations.json
deleted file mode 100644
index 9d032c0..0000000
--- a/testdata/list_group_iterations.json
+++ /dev/null
@@ -1,16 +0,0 @@
-[
-    {
-      "id": 53,
-      "iid": 13,
-      "sequence": 1,
-      "group_id": 5,
-      "title": "Iteration II",
-      "description": "Ipsum Lorem ipsum",
-      "state": 2,
-      "created_at": "2020-01-27T05:07:12.573Z",
-      "updated_at": "2020-01-27T05:07:12.573Z",
-      "due_date": "2020-02-01",
-      "start_date": "2020-02-14",
-      "web_url": "http://gitlab.example.com/groups/my-group/-/iterations/13"
-    }
-]