1package gitlab
2
3import (
4	"fmt"
5	"time"
6)
7
8// ReleasesService handles communication with the releases methods
9// of the GitLab API.
10//
11// GitLab API docs: https://docs.gitlab.com/ce/api/releases/index.html
12type ReleasesService struct {
13	client *Client
14}
15
16// Release represents a project release.
17//
18// GitLab API docs:
19// https://docs.gitlab.com/ce/api/releases/index.html#list-releases
20type Release struct {
21	TagName         string     `json:"tag_name"`
22	Name            string     `json:"name"`
23	Description     string     `json:"description,omitempty"`
24	DescriptionHTML string     `json:"description_html,omitempty"`
25	CreatedAt       *time.Time `json:"created_at,omitempty"`
26	Author          struct {
27		ID        int    `json:"id"`
28		Name      string `json:"name"`
29		Username  string `json:"username"`
30		State     string `json:"state"`
31		AvatarURL string `json:"avatar_url"`
32		WebURL    string `json:"web_url"`
33	} `json:"author"`
34	Commit Commit `json:"commit"`
35	Assets struct {
36		Count   int `json:"count"`
37		Sources []struct {
38			Format string `json:"format"`
39			URL    string `json:"url"`
40		} `json:"sources"`
41		Links []*ReleaseLink `json:"links"`
42	} `json:"assets"`
43}
44
45// ListReleasesOptions represents ListReleases() options.
46//
47// GitLab API docs:
48// https://docs.gitlab.com/ce/api/releases/index.html#list-releases
49type ListReleasesOptions ListOptions
50
51// ListReleases gets a pagenated of releases accessible by the authenticated user.
52//
53// GitLab API docs:
54// https://docs.gitlab.com/ce/api/releases/index.html#list-releases
55func (s *ReleasesService) ListReleases(pid interface{}, opt *ListReleasesOptions, options ...OptionFunc) ([]*Release, *Response, error) {
56	project, err := parseID(pid)
57	if err != nil {
58		return nil, nil, err
59	}
60	u := fmt.Sprintf("projects/%s/releases", pathEscape(project))
61
62	req, err := s.client.NewRequest("GET", u, opt, options)
63	if err != nil {
64		return nil, nil, err
65	}
66
67	var rs []*Release
68	resp, err := s.client.Do(req, &rs)
69	if err != nil {
70		return nil, resp, err
71	}
72
73	return rs, resp, err
74}
75
76// GetRelease returns a single release, identified by a tag name.
77//
78// GitLab API docs:
79// https://docs.gitlab.com/ce/api/releases/index.html#get-a-release-by-a-tag-name
80func (s *ReleasesService) GetRelease(pid interface{}, tagName string, options ...OptionFunc) (*Release, *Response, error) {
81	project, err := parseID(pid)
82	if err != nil {
83		return nil, nil, err
84	}
85	u := fmt.Sprintf("projects/%s/releases/%s", pathEscape(project), tagName)
86
87	req, err := s.client.NewRequest("GET", u, nil, options)
88	if err != nil {
89		return nil, nil, err
90	}
91
92	r := new(Release)
93	resp, err := s.client.Do(req, r)
94	if err != nil {
95		return nil, resp, err
96	}
97
98	return r, resp, err
99}
100
101// ReleaseAssets represents release assets in CreateRelease() options
102//
103// GitLab API docs:
104// https://docs.gitlab.com/ce/api/releases/index.html#create-a-release
105type ReleaseAssets struct {
106	Links []*ReleaseAssetLink `url:"links" json:"links"`
107}
108
109// ReleaseAssetLink represents release asset link in CreateRelease() options
110//
111// GitLab API docs:
112// https://docs.gitlab.com/ce/api/releases/index.html#create-a-release
113type ReleaseAssetLink struct {
114	Name string `url:"name" json:"name"`
115	URL  string `url:"url" json:"url"`
116}
117
118// CreateReleaseOptions represents CreateRelease() options.
119//
120// GitLab API docs:
121// https://docs.gitlab.com/ce/api/releases/index.html#create-a-release
122type CreateReleaseOptions struct {
123	Name        *string        `url:"name" json:"name"`
124	TagName     *string        `url:"tag_name" json:"tag_name"`
125	Description *string        `url:"description" json:"description"`
126	Ref         *string        `url:"ref,omitempty" json:"ref,omitempty"`
127	Assets      *ReleaseAssets `url:"assets,omitempty" json:"assets,omitempty"`
128}
129
130// CreateRelease creates a release.
131//
132// GitLab API docs:
133// https://docs.gitlab.com/ce/api/releases/index.html#create-a-release
134func (s *ReleasesService) CreateRelease(pid interface{}, opts *CreateReleaseOptions, options ...OptionFunc) (*Release, *Response, error) {
135	project, err := parseID(pid)
136	if err != nil {
137		return nil, nil, err
138	}
139	u := fmt.Sprintf("projects/%s/releases", pathEscape(project))
140
141	req, err := s.client.NewRequest("POST", u, opts, options)
142	if err != nil {
143		return nil, nil, err
144	}
145
146	r := new(Release)
147	resp, err := s.client.Do(req, r)
148	if err != nil {
149		return nil, resp, err
150	}
151
152	return r, resp, err
153}
154
155// UpdateReleaseOptions represents UpdateRelease() options.
156//
157// GitLab API docs:
158// https://docs.gitlab.com/ce/api/releases/index.html#update-a-release
159type UpdateReleaseOptions struct {
160	Name        *string `url:"name" json:"name"`
161	Description *string `url:"description" json:"description"`
162}
163
164// UpdateRelease updates a release.
165//
166// GitLab API docs:
167// https://docs.gitlab.com/ce/api/releases/index.html#update-a-release
168func (s *ReleasesService) UpdateRelease(pid interface{}, tagName string, opts *UpdateReleaseOptions, options ...OptionFunc) (*Release, *Response, error) {
169	project, err := parseID(pid)
170	if err != nil {
171		return nil, nil, err
172	}
173	u := fmt.Sprintf("projects/%s/releases/%s", pathEscape(project), tagName)
174
175	req, err := s.client.NewRequest("PUT", u, opts, options)
176	if err != nil {
177		return nil, nil, err
178	}
179
180	r := new(Release)
181	resp, err := s.client.Do(req, &r)
182	if err != nil {
183		return nil, resp, err
184	}
185
186	return r, resp, err
187}
188
189// DeleteRelease deletes a release.
190//
191// GitLab API docs:
192// https://docs.gitlab.com/ce/api/releases/index.html#delete-a-release
193func (s *ReleasesService) DeleteRelease(pid interface{}, tagName string, options ...OptionFunc) (*Release, *Response, error) {
194	project, err := parseID(pid)
195	if err != nil {
196		return nil, nil, err
197	}
198	u := fmt.Sprintf("projects/%s/releases/%s", pathEscape(project), tagName)
199
200	req, err := s.client.NewRequest("DELETE", u, nil, options)
201	if err != nil {
202		return nil, nil, err
203	}
204
205	r := new(Release)
206	resp, err := s.client.Do(req, r)
207	if err != nil {
208		return nil, resp, err
209	}
210
211	return r, resp, err
212}
213