1//
2// Copyright 2021, Sander van Harmelen
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8//     http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
16
17package gitlab
18
19import (
20	"fmt"
21	"net/http"
22	"time"
23)
24
25// PipelineSchedulesService handles communication with the pipeline
26// schedules related methods of the GitLab API.
27//
28// GitLab API docs: https://docs.gitlab.com/ce/api/pipeline_schedules.html
29type PipelineSchedulesService struct {
30	client *Client
31}
32
33// PipelineSchedule represents a pipeline schedule.
34//
35// GitLab API docs:
36// https://docs.gitlab.com/ce/api/pipeline_schedules.html
37type PipelineSchedule struct {
38	ID           int        `json:"id"`
39	Description  string     `json:"description"`
40	Ref          string     `json:"ref"`
41	Cron         string     `json:"cron"`
42	CronTimezone string     `json:"cron_timezone"`
43	NextRunAt    *time.Time `json:"next_run_at"`
44	Active       bool       `json:"active"`
45	CreatedAt    *time.Time `json:"created_at"`
46	UpdatedAt    *time.Time `json:"updated_at"`
47	Owner        *User      `json:"owner"`
48	LastPipeline struct {
49		ID     int    `json:"id"`
50		SHA    string `json:"sha"`
51		Ref    string `json:"ref"`
52		Status string `json:"status"`
53	} `json:"last_pipeline"`
54	Variables []*PipelineVariable `json:"variables"`
55}
56
57// ListPipelineSchedulesOptions represents the available ListPipelineTriggers() options.
58//
59// GitLab API docs:
60// https://docs.gitlab.com/ce/api/pipeline_triggers.html#list-project-triggers
61type ListPipelineSchedulesOptions ListOptions
62
63// ListPipelineSchedules gets a list of project triggers.
64//
65// GitLab API docs:
66// https://docs.gitlab.com/ce/api/pipeline_schedules.html
67func (s *PipelineSchedulesService) ListPipelineSchedules(pid interface{}, opt *ListPipelineSchedulesOptions, options ...RequestOptionFunc) ([]*PipelineSchedule, *Response, error) {
68	project, err := parseID(pid)
69	if err != nil {
70		return nil, nil, err
71	}
72	u := fmt.Sprintf("projects/%s/pipeline_schedules", PathEscape(project))
73
74	req, err := s.client.NewRequest(http.MethodGet, u, opt, options)
75	if err != nil {
76		return nil, nil, err
77	}
78
79	var ps []*PipelineSchedule
80	resp, err := s.client.Do(req, &ps)
81	if err != nil {
82		return nil, resp, err
83	}
84
85	return ps, resp, err
86}
87
88// GetPipelineSchedule gets a pipeline schedule.
89//
90// GitLab API docs:
91// https://docs.gitlab.com/ce/api/pipeline_schedules.html
92func (s *PipelineSchedulesService) GetPipelineSchedule(pid interface{}, schedule int, options ...RequestOptionFunc) (*PipelineSchedule, *Response, error) {
93	project, err := parseID(pid)
94	if err != nil {
95		return nil, nil, err
96	}
97	u := fmt.Sprintf("projects/%s/pipeline_schedules/%d", PathEscape(project), schedule)
98
99	req, err := s.client.NewRequest(http.MethodGet, u, nil, options)
100	if err != nil {
101		return nil, nil, err
102	}
103
104	p := new(PipelineSchedule)
105	resp, err := s.client.Do(req, p)
106	if err != nil {
107		return nil, resp, err
108	}
109
110	return p, resp, err
111}
112
113// CreatePipelineScheduleOptions represents the available
114// CreatePipelineSchedule() options.
115//
116// GitLab API docs:
117// https://docs.gitlab.com/ce/api/pipeline_schedules.html#create-a-new-pipeline-schedule
118type CreatePipelineScheduleOptions struct {
119	Description  *string `url:"description" json:"description"`
120	Ref          *string `url:"ref" json:"ref"`
121	Cron         *string `url:"cron" json:"cron"`
122	CronTimezone *string `url:"cron_timezone,omitempty" json:"cron_timezone,omitempty"`
123	Active       *bool   `url:"active,omitempty" json:"active,omitempty"`
124}
125
126// CreatePipelineSchedule creates a pipeline schedule.
127//
128// GitLab API docs:
129// https://docs.gitlab.com/ce/api/pipeline_schedules.html#create-a-new-pipeline-schedule
130func (s *PipelineSchedulesService) CreatePipelineSchedule(pid interface{}, opt *CreatePipelineScheduleOptions, options ...RequestOptionFunc) (*PipelineSchedule, *Response, error) {
131	project, err := parseID(pid)
132	if err != nil {
133		return nil, nil, err
134	}
135	u := fmt.Sprintf("projects/%s/pipeline_schedules", PathEscape(project))
136
137	req, err := s.client.NewRequest(http.MethodPost, u, opt, options)
138	if err != nil {
139		return nil, nil, err
140	}
141
142	p := new(PipelineSchedule)
143	resp, err := s.client.Do(req, p)
144	if err != nil {
145		return nil, resp, err
146	}
147
148	return p, resp, err
149}
150
151// EditPipelineScheduleOptions represents the available
152// EditPipelineSchedule() options.
153//
154// GitLab API docs:
155// https://docs.gitlab.com/ce/api/pipeline_schedules.html#create-a-new-pipeline-schedule
156type EditPipelineScheduleOptions struct {
157	Description  *string `url:"description,omitempty" json:"description,omitempty"`
158	Ref          *string `url:"ref,omitempty" json:"ref,omitempty"`
159	Cron         *string `url:"cron,omitempty" json:"cron,omitempty"`
160	CronTimezone *string `url:"cron_timezone,omitempty" json:"cron_timezone,omitempty"`
161	Active       *bool   `url:"active,omitempty" json:"active,omitempty"`
162}
163
164// EditPipelineSchedule edits a pipeline schedule.
165//
166// GitLab API docs:
167// https://docs.gitlab.com/ce/api/pipeline_schedules.html#edit-a-pipeline-schedule
168func (s *PipelineSchedulesService) EditPipelineSchedule(pid interface{}, schedule int, opt *EditPipelineScheduleOptions, options ...RequestOptionFunc) (*PipelineSchedule, *Response, error) {
169	project, err := parseID(pid)
170	if err != nil {
171		return nil, nil, err
172	}
173	u := fmt.Sprintf("projects/%s/pipeline_schedules/%d", PathEscape(project), schedule)
174
175	req, err := s.client.NewRequest(http.MethodPut, u, opt, options)
176	if err != nil {
177		return nil, nil, err
178	}
179
180	p := new(PipelineSchedule)
181	resp, err := s.client.Do(req, p)
182	if err != nil {
183		return nil, resp, err
184	}
185
186	return p, resp, err
187}
188
189// TakeOwnershipOfPipelineSchedule sets the owner of the specified
190// pipeline schedule to the user issuing the request.
191//
192// GitLab API docs:
193// https://docs.gitlab.com/ce/api/pipeline_schedules.html#take-ownership-of-a-pipeline-schedule
194func (s *PipelineSchedulesService) TakeOwnershipOfPipelineSchedule(pid interface{}, schedule int, options ...RequestOptionFunc) (*PipelineSchedule, *Response, error) {
195	project, err := parseID(pid)
196	if err != nil {
197		return nil, nil, err
198	}
199	u := fmt.Sprintf("projects/%s/pipeline_schedules/%d/take_ownership", PathEscape(project), schedule)
200
201	req, err := s.client.NewRequest(http.MethodPost, u, nil, options)
202	if err != nil {
203		return nil, nil, err
204	}
205
206	p := new(PipelineSchedule)
207	resp, err := s.client.Do(req, p)
208	if err != nil {
209		return nil, resp, err
210	}
211
212	return p, resp, err
213}
214
215// DeletePipelineSchedule deletes a pipeline schedule.
216//
217// GitLab API docs:
218// https://docs.gitlab.com/ce/api/pipeline_schedules.html#delete-a-pipeline-schedule
219func (s *PipelineSchedulesService) DeletePipelineSchedule(pid interface{}, schedule int, options ...RequestOptionFunc) (*Response, error) {
220	project, err := parseID(pid)
221	if err != nil {
222		return nil, err
223	}
224	u := fmt.Sprintf("projects/%s/pipeline_schedules/%d", PathEscape(project), schedule)
225
226	req, err := s.client.NewRequest(http.MethodDelete, u, nil, options)
227	if err != nil {
228		return nil, err
229	}
230
231	return s.client.Do(req, nil)
232}
233
234// RunPipelineSchedule triggers a new scheduled pipeline to run immediately.
235//
236// Gitlab API docs:
237// https://docs.gitlab.com/ce/api/pipeline_schedules.html#run-a-scheduled-pipeline-immediately
238func (s *PipelineSchedulesService) RunPipelineSchedule(pid interface{}, schedule int, options ...RequestOptionFunc) (*Response, error) {
239	project, err := parseID(pid)
240	if err != nil {
241		return nil, err
242	}
243	u := fmt.Sprintf("projects/%s/pipeline_schedules/%d/play", PathEscape(project), schedule)
244
245	req, err := s.client.NewRequest(http.MethodPost, u, nil, options)
246	if err != nil {
247		return nil, err
248	}
249
250	return s.client.Do(req, nil)
251}
252
253// CreatePipelineScheduleVariableOptions represents the available
254// CreatePipelineScheduleVariable() options.
255//
256// GitLab API docs:
257// https://docs.gitlab.com/ce/api/pipeline_schedules.html#create-a-new-pipeline-schedule
258type CreatePipelineScheduleVariableOptions struct {
259	Key          *string `url:"key" json:"key"`
260	Value        *string `url:"value" json:"value"`
261	VariableType *string `url:"variable_type,omitempty" json:"variable_type,omitempty"`
262}
263
264// CreatePipelineScheduleVariable creates a pipeline schedule variable.
265//
266// GitLab API docs:
267// https://docs.gitlab.com/ce/api/pipeline_schedules.html#create-a-new-pipeline-schedule
268func (s *PipelineSchedulesService) CreatePipelineScheduleVariable(pid interface{}, schedule int, opt *CreatePipelineScheduleVariableOptions, options ...RequestOptionFunc) (*PipelineVariable, *Response, error) {
269	project, err := parseID(pid)
270	if err != nil {
271		return nil, nil, err
272	}
273	u := fmt.Sprintf("projects/%s/pipeline_schedules/%d/variables", PathEscape(project), schedule)
274
275	req, err := s.client.NewRequest(http.MethodPost, u, opt, options)
276	if err != nil {
277		return nil, nil, err
278	}
279
280	p := new(PipelineVariable)
281	resp, err := s.client.Do(req, p)
282	if err != nil {
283		return nil, resp, err
284	}
285
286	return p, resp, err
287}
288
289// EditPipelineScheduleVariableOptions represents the available
290// EditPipelineScheduleVariable() options.
291//
292// GitLab API docs:
293// https://docs.gitlab.com/ce/api/pipeline_schedules.html#edit-a-pipeline-schedule-variable
294type EditPipelineScheduleVariableOptions struct {
295	Value        *string `url:"value" json:"value"`
296	VariableType *string `url:"variable_type,omitempty" json:"variable_type,omitempty"`
297}
298
299// EditPipelineScheduleVariable creates a pipeline schedule variable.
300//
301// GitLab API docs:
302// https://docs.gitlab.com/ce/api/pipeline_schedules.html#edit-a-pipeline-schedule-variable
303func (s *PipelineSchedulesService) EditPipelineScheduleVariable(pid interface{}, schedule int, key string, opt *EditPipelineScheduleVariableOptions, options ...RequestOptionFunc) (*PipelineVariable, *Response, error) {
304	project, err := parseID(pid)
305	if err != nil {
306		return nil, nil, err
307	}
308	u := fmt.Sprintf("projects/%s/pipeline_schedules/%d/variables/%s", PathEscape(project), schedule, key)
309
310	req, err := s.client.NewRequest(http.MethodPut, u, opt, options)
311	if err != nil {
312		return nil, nil, err
313	}
314
315	p := new(PipelineVariable)
316	resp, err := s.client.Do(req, p)
317	if err != nil {
318		return nil, resp, err
319	}
320
321	return p, resp, err
322}
323
324// DeletePipelineScheduleVariable creates a pipeline schedule variable.
325//
326// GitLab API docs:
327// https://docs.gitlab.com/ce/api/pipeline_schedules.html#delete-a-pipeline-schedule-variable
328func (s *PipelineSchedulesService) DeletePipelineScheduleVariable(pid interface{}, schedule int, key string, options ...RequestOptionFunc) (*PipelineVariable, *Response, error) {
329	project, err := parseID(pid)
330	if err != nil {
331		return nil, nil, err
332	}
333	u := fmt.Sprintf("projects/%s/pipeline_schedules/%d/variables/%s", PathEscape(project), schedule, key)
334
335	req, err := s.client.NewRequest(http.MethodDelete, u, nil, options)
336	if err != nil {
337		return nil, nil, err
338	}
339
340	p := new(PipelineVariable)
341	resp, err := s.client.Do(req, p)
342	if err != nil {
343		return nil, resp, err
344	}
345
346	return p, resp, err
347}
348