gitlab-customer-support-operations_gitlab 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. checksums.yaml +7 -0
  2. data/lib/support_ops_gitlab/gitlab/badges.rb +229 -0
  3. data/lib/support_ops_gitlab/gitlab/base.rb +552 -0
  4. data/lib/support_ops_gitlab/gitlab/client.rb +51 -0
  5. data/lib/support_ops_gitlab/gitlab/commits.rb +198 -0
  6. data/lib/support_ops_gitlab/gitlab/configuration.rb +86 -0
  7. data/lib/support_ops_gitlab/gitlab/epics.rb +325 -0
  8. data/lib/support_ops_gitlab/gitlab/events.rb +167 -0
  9. data/lib/support_ops_gitlab/gitlab/gpg_keys.rb +64 -0
  10. data/lib/support_ops_gitlab/gitlab/group_memberships.rb +33 -0
  11. data/lib/support_ops_gitlab/gitlab/groups.rb +431 -0
  12. data/lib/support_ops_gitlab/gitlab/invitations.rb +72 -0
  13. data/lib/support_ops_gitlab/gitlab/issues.rb +606 -0
  14. data/lib/support_ops_gitlab/gitlab/jobs.rb +61 -0
  15. data/lib/support_ops_gitlab/gitlab/markdown.rb +54 -0
  16. data/lib/support_ops_gitlab/gitlab/merge_requests.rb +411 -0
  17. data/lib/support_ops_gitlab/gitlab/milestones.rb +195 -0
  18. data/lib/support_ops_gitlab/gitlab/namespaces.rb +184 -0
  19. data/lib/support_ops_gitlab/gitlab/notes.rb +182 -0
  20. data/lib/support_ops_gitlab/gitlab/pipelines.rb +258 -0
  21. data/lib/support_ops_gitlab/gitlab/project_access_tokens.rb +245 -0
  22. data/lib/support_ops_gitlab/gitlab/project_memberships.rb +33 -0
  23. data/lib/support_ops_gitlab/gitlab/project_webhook_events.rb +33 -0
  24. data/lib/support_ops_gitlab/gitlab/project_webhooks.rb +218 -0
  25. data/lib/support_ops_gitlab/gitlab/projects.rb +741 -0
  26. data/lib/support_ops_gitlab/gitlab/repository_files.rb +102 -0
  27. data/lib/support_ops_gitlab/gitlab/repository_submodules.rb +78 -0
  28. data/lib/support_ops_gitlab/gitlab/ssh_keys.rb +67 -0
  29. data/lib/support_ops_gitlab/gitlab/user_emails.rb +147 -0
  30. data/lib/support_ops_gitlab/gitlab/user_memberships.rb +21 -0
  31. data/lib/support_ops_gitlab/gitlab/user_tokens.rb +344 -0
  32. data/lib/support_ops_gitlab/gitlab/users.rb +1059 -0
  33. data/lib/support_ops_gitlab/gitlab.rb +45 -0
  34. data/lib/support_ops_gitlab.rb +28 -0
  35. metadata +251 -0
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Defines the module SupportOps.
4
+ module SupportOps
5
+ # Defines the module GitLab
6
+ module GitLab
7
+ ##
8
+ # Defines the class Markdown within the module {SupportOps::GitLab}.
9
+ #
10
+ # @author Jason Colyer
11
+ # @since 1.0.0
12
+ # @attr [Array] allowed_email_domains_list Comma-separated list of email address domains to allow group access
13
+ class Markdown < SupportOps::GitLab::Base
14
+ define_attributes :html
15
+ readonly_attributes :html
16
+
17
+ ##
18
+ # Renders text using Markdown
19
+ #
20
+ # @author Jason Colyer
21
+ # @since 1.0.0
22
+ # @param text [String] The text to render
23
+ # @param gfm [Boolean optional] If this should render as GitLab Flavored Markdown or not (defaults to false)
24
+ # @param project [String optiona] The project slug to use as a template (defaults to gitlab-org/gitlab)
25
+ # @see
26
+ # https://docs.gitlab.com/ee/api/markdown.html#render-an-arbitrary-markdown-document
27
+ # GitLab API > Markdown > Render an arbitrary Markdown document
28
+ # @example
29
+ # require 'support_ops_gitlab'
30
+ #
31
+ # SupportOps::GitLab::Configuration.configure do |config|
32
+ # config.url = 'https://gitlab.com/api/v4'
33
+ # config.token = 'abc123'
34
+ # end
35
+ #
36
+ # markdown = SupportOps::GitLab::Markdown.convert('This is a test')
37
+ # pp markdown.html
38
+ # # => "<p data-sourcepos=\"1:1-1:14\">This is a test</p>"
39
+ def self.render(text, gfm = false, project = 'gitlab-org/gitlab')
40
+ data = {
41
+ text: text,
42
+ gfm: gfm,
43
+ project: project
44
+ }.to_json
45
+ response = client.connection.post('markdown', data)
46
+ body = Oj.load(response.body)
47
+ raise "Unable to render markdown => #{body}" unless response.status == 201
48
+ Markdown.new(body)
49
+ end
50
+
51
+ private
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,411 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Defines the module SupportOps.
4
+ module SupportOps
5
+ # Defines the module GitLab
6
+ module GitLab
7
+ ##
8
+ # Defines the class MergeRequests within the module {SupportOps::GitLab}.
9
+ #
10
+ # @author Jason Colyer
11
+ # @since 1.0.0
12
+ # @attr [Boolean] allow_collaboration Allow commits from members who can merge to the target branch
13
+ # @attr [Boolean] allow_maintainer_to_push Alias of allow_collaboration
14
+ # @attr [Hash] assignee Information on the first merge request assignee
15
+ # @attr [Array] assignees An array of users assigned to the merge request
16
+ # @attr [Hash] author The author of the merge request
17
+ # @attr [String] closed_at The timestamp the merge request was closed at
18
+ # @attr [Hash] closed_by The user who closed the merge request
19
+ # @attr [String] created_at The timestamp of when the ismerge requestsue was created
20
+ # @attr [String] description The merge request's description
21
+ # @attr [String] detailed_merge_status Detailed merge status of the merge request
22
+ # @attr [Boolean] discussion_locked If discussion on the merge request is locked or not
23
+ # @attr [Integer] downvotes The number of downvotes the merge request has
24
+ # @attr [Boolean] draft If the merge request is in draft mode or not
25
+ # @attr [Boolean] force_remove_source_branch Indicates if the project settings lead to source branch deletion after merge
26
+ # @attr [Integer] id The global ID or URL-encoded path of the project
27
+ # @attr [Integer] iid The internal ID of a project’s merge request
28
+ # @attr [Boolean] imported If the merge request was imported or not
29
+ # @attr [String] imported_from
30
+ # @attr [Array] labels Comma-separated list of label names
31
+ # @attr [String] merge_after Date after which the merge request can be merged
32
+ # @attr [String] merge_commit_sha SHA of the merge request commit; returns null until merged
33
+ # @attr [String] merged_at The timestamp the merge request was merged
34
+ # @attr [String] merge_status Status of the merge request; can be unchecked, checking, can_be_merged, cannot_be_merged, or cannot_be_merged_recheck. Affects the has_conflicts property
35
+ # @attr [String] merge_user The user who merged this merge request, the user who set it to auto-merge, or null
36
+ # @attr [Boolean] merge_when_pipeline_succeeds Indicates if the merge is set to merge when its pipeline succeeds
37
+ # @attr [Hash] milestone The milestone the merge request is attached to
38
+ # @attr [String] prepared_at Timestamp of when the merge request was prepared; this field populates one time, only after all the preparation steps complete, and is not updated if more changes are added
39
+ # @attr [Integer] project_id The ID of the project the merge request is within
40
+ # @attr [Hash] references Reference tags for the merge request
41
+ # @attr [Array] reviewers Reviewers of the merge request
42
+ # @attr [String] sha Diff head SHA of the merge request
43
+ # @attr [Boolean] should_remove_source_branch Indicates if the source branch of the merge request should be deleted after merge
44
+ # @attr [String] source_branch Source branch of the merge request
45
+ # @attr [Integer] source_project_id ID of the merge request source project
46
+ # @attr [Boolean] squash Indicates if squash on merge is enabled
47
+ # @attr [String] squash_commit_sha SHA of the squash commit; empty until merged.
48
+ # @attr [String] state The current state of the merge request
49
+ # @attr [String] target_branch Target branch of the merge request
50
+ # @attr [Integer] target_project_id ID of the merge request target project
51
+ # @attr [Hash] task_completion_status Information on the task status of a merge request
52
+ # @attr [Hash] time_stats Information on the time spent on the merge request
53
+ # @attr [String] title The mnerge request title
54
+ # @attr [String] updated_at The timestamp of when the merge request was last updated
55
+ # @attr [Integer] upvotes The number of upvotes on a merge request
56
+ # @attr [Integer] user_notes_count The number of notes on the merge request
57
+ # @attr [String] web_url The URL of the merge request
58
+ # @todo Populate readonly_attributes
59
+ # @todo A lot of things listed at https://docs.gitlab.com/api/merge_requests
60
+ # @todo A lot of things listed at https://docs.gitlab.com/api/merge_request_approvals/
61
+ # @todo A lot of things listed at https://docs.gitlab.com/api/merge_request_approval_settings/
62
+ # @todo A lot of things listed at https://docs.gitlab.com/api/merge_request_context_commits/
63
+ # @todo List issues related to the merge request => https://docs.gitlab.com/api/merge_requests/#list-issues-related-to-the-merge-request
64
+ class MergeRequests < SupportOps::GitLab::Base
65
+ # @!parse
66
+ # # Subscribe to a merge request
67
+ # #
68
+ # # @author Jason Colyer
69
+ # # @since 1.0.0
70
+ # # @return [Object] Instance of {SupportOps::GitLab::MergeRequests}
71
+ # # @note This is inherited from {SupportOps::GitLab::Base#subscribe!}
72
+ # # @see
73
+ # # https://docs.gitlab.com/api/merge_requests/#subscribe-to-a-merge-request
74
+ # # GitLab API > Merge requests > Subscribe to a merge request
75
+ # # @example
76
+ # # require 'support_ops_gitlab'
77
+ # #
78
+ # # SupportOps::GitLab::Configuration.configure do |config|
79
+ # # config.token = ENV.fetch('GL_TOKEN')
80
+ # # config.url = 'https://gitlab.com/api/v4'
81
+ # # end
82
+ # #
83
+ # # existing_mr = SupportOps::GitLab::MergeRequests.get(iid: 28, project_id: 123456)
84
+ # # existing_mr.subscribe!
85
+ # def subscribe!; end
86
+ # @!parse
87
+ # # Unsubscribe to a merge request
88
+ # #
89
+ # # @author Jason Colyer
90
+ # # @since 1.0.0
91
+ # # @return [Object] Instance of {SupportOps::GitLab::MergeRequests}
92
+ # # @note This is inherited from {SupportOps::GitLab::Base#unsubscribe!}
93
+ # # @see
94
+ # # https://docs.gitlab.com/api/merge_requests/#unsubscribe-to-a-merge-request
95
+ # # GitLab API > Merge requests > Unsubscribe to a merge request
96
+ # # @example
97
+ # # require 'support_ops_gitlab'
98
+ # #
99
+ # # SupportOps::GitLab::Configuration.configure do |config|
100
+ # # config.token = ENV.fetch('GL_TOKEN')
101
+ # # config.url = 'https://gitlab.com/api/v4'
102
+ # # end
103
+ # #
104
+ # # existing_mr = SupportOps::GitLab::MergeRequests.get(iid: 28, project_id: 123456)
105
+ # # existing_mr.unsubscribe!
106
+ # def unsubscribe!; end
107
+ # @!parse
108
+ # # List notes on a merge request
109
+ # #
110
+ # # @author Jason Colyer
111
+ # # @since 1.0.0
112
+ # # @return [Boolean]
113
+ # # @note This is inherited from {SupportOps::GitLab::Base#notes}
114
+ # # @see
115
+ # # https://docs.gitlab.com/api/notes/#list-all-merge-request-notes
116
+ # # GitLab API > Notes (comments) > List all merge request notes
117
+ # # @example
118
+ # # require 'support_ops_gitlab'
119
+ # #
120
+ # # SupportOps::GitLab::Configuration.configure do |config|
121
+ # # config.token = ENV.fetch('GL_TOKEN')
122
+ # # config.url = 'https://gitlab.com/api/v4'
123
+ # # end
124
+ # #
125
+ # # existing_mr = SupportOps::GitLab::MergeRequests.get(iid: 28, project_id: 123456)
126
+ # # notes = existing_mr.notes
127
+ # # pp notes.count
128
+ # # # => 7
129
+ # def notes; end
130
+ define_attributes :allow_collaboration, :allow_maintainer_to_push,
131
+ :assignee, :assignees, :author, :closed_at, :closed_by,
132
+ :created_at, :description, :detailed_merge_status,
133
+ :discussion_locked, :downvotes, :draft,
134
+ :force_remove_source_branch, :id, :iid, :imported,
135
+ :imported_from, :labels, :merge_after,
136
+ :merge_commit_sha, :merged_at, :merge_status,
137
+ :merge_user, :merge_when_pipeline_succeeds, :milestone,
138
+ :prepared_at, :project_id, :references, :reviewers,
139
+ :sha, :should_remove_source_branch, :source_branch,
140
+ :source_project_id, :squash, :squash_commit_sha, :state,
141
+ :target_branch, :target_project_id,
142
+ :task_completion_status, :time_stats, :title,
143
+ :updated_at, :upvotes, :user_notes_count, :web_url
144
+ readonly_attributes :id
145
+
146
+ ##
147
+ # Lists issues
148
+ #
149
+ # @author Jason Colyer
150
+ # @since 1.0.0
151
+ # @overload list(key: value)
152
+ # @param approved [String optional] Filters merge requests by their approved status; 'yes' returns only approved merge requests; 'no' returns only non-approved merge requests; requires the mr_approved_filter feature flag, disabled by default
153
+ # @param approved_by_ids [Array optional] Returns the merge requests approved by all the users with the given id, up to 5 users; 'None' returns merge requests with no approvals; 'Any' returns merge requests with an approval
154
+ # @param approved_by_usernames [Array optional] Returns the merge requests approved by all the users with the given username, up to 5 users; 'None' returns merge requests with no approvals; 'Any' returns merge requests with an approval
155
+ # @param approver_ids [Array optional] Returns merge requests which have specified all the users with the given id as individual approvers; 'None' returns merge requests without approvers; 'Any' returns merge requests with an approver
156
+ # @param assignee_id [Integer optional] Returns merge requests assigned to the given user id; 'None' returns unassigned merge requests; 'Any' returns merge requests with an assignee
157
+ # @param author_id [Integer optional] Returns merge requests created by the given user id; mutually exclusive with author_username
158
+ # @param author_username [String optional] Returns merge requests created by the given username; mutually exclusive with author_id
159
+ # @param created_after [String optional] Returns merge requests created on or after the given time; expected in ISO 8601 format (2019-03-15T08:00:00Z)
160
+ # @param created_before [String optional] Returns merge requests created on or before the given time; expected in ISO 8601 format (2019-03-15T08:00:00Z)
161
+ # @param labels [String optional] Returns merge requests matching a comma-separated list of labels; 'None' lists all merge requests with no labels; 'Any' lists all merge requests with at least one label; predefined names are case-insensitive
162
+ # @param merge_user_id [Integer optional] Returns merge requests merged by the user with the given user id; mutually exclusive with merge_user_username
163
+ # @param merge_user_username [String optional] Returns merge requests merged by the user with the given username; mutually exclusive with merge_user_id
164
+ # @param milestone [String optional] Returns merge requests for a specific milestone; 'None' returns merge requests with no milestone; 'Any' returns merge requests that have an assigned milestone
165
+ # @param my_reaction_emoji [String optional] Returns merge requests reacted by the authenticated user by the given emoji; 'None' returns issues not given a reaction; 'Any' returns issues given at least one reaction
166
+ # @param non_archived [Boolean optional] Returns merge requests from non archived projects only
167
+ # @param order_by [String optional] Returns merge requests ordered by created_at, title or updated_at fields
168
+ # @param project_id [Integer optional] The project to scope the list to (not providing it scopes it to the whole instance)
169
+ # @param reviewer_id [Integer optional] Returns merge requests which have the user as a reviewer with the given user id; 'None' returns merge requests with no reviewers; 'Any' returns merge requests with any reviewer; mutually exclusive with reviewer_username
170
+ # @param reviewer_username [String optional] Returns merge requests which have the user as a reviewer with the given username; 'None' returns merge requests with no reviewers; 'Any' returns merge requests with any reviewer; mutually exclusive with reviewer_id
171
+ # @param scope [String optional] Returns merge requests for the given scope: created_by_me, assigned_to_me or all
172
+ # @param search [String optional] Search merge requests against their title and description
173
+ # @param sort [String optional] Returns merge requests sorted in asc or desc order
174
+ # @param source_branch [String optional] Returns merge requests with the given source branch
175
+ # @param state [String optional] Returns all merge requests (all) or just those that are opened, closed, locked, or merged
176
+ # @param target_branch [String optional] Returns merge requests with the given target branch
177
+ # @param updated_after [String optional] Returns merge requests updated on or after the given time; expected in ISO 8601 format (2019-03-15T08:00:00Z)
178
+ # @param updated_before [String optional] Returns merge requests updated on or before the given time; expected in ISO 8601 format (2019-03-15T08:00:00Z)
179
+ # @param limit [Integer optional] The limit to the number of users
180
+ # returned. Default to 0 (i.e. no limit)
181
+ # @return [Array]
182
+ # @see
183
+ # https://docs.gitlab.com/api/merge_requests/#list-merge-requests
184
+ # GitLab API > Merge requests > List merge requests
185
+ # @see SupportOps::GitLab::Configuration Setting up a client
186
+ # @example
187
+ # require 'support_ops_gitlab'
188
+ #
189
+ # SupportOps::GitLab::Configuration.configure do |config|
190
+ # config.url = 'https://gitlab.example.com/api/v4'
191
+ # config.token = 'abc123'
192
+ # end
193
+ #
194
+ # mrs = SupportOps::GitLab::MergeRequests.list(project_id: 123456)
195
+ # pp mrs.count
196
+ # # => 30
197
+ # pp mrs.last.due_date
198
+ # # => "2018-07-31"
199
+ def self.list(**args)
200
+ args[:approved] = nil unless args[:approved]
201
+ args[:approved_by_ids] = nil unless args[:approved_by_ids]
202
+ args[:approved_by_usernames] = nil unless args[:approved_by_usernames]
203
+ args[:approver_ids] = nil unless args[:approver_ids]
204
+ args[:assignee_id] = nil unless args[:assignee_id]
205
+ args[:author_id] = nil unless args[:author_id]
206
+ args[:author_username] = nil unless args[:author_username]
207
+ args[:created_after] = nil unless args[:created_after]
208
+ args[:created_before] = nil unless args[:created_before]
209
+ args[:labels] = nil unless args[:labels]
210
+ args[:merge_user_id] = nil unless args[:merge_user_id]
211
+ args[:merge_user_username] = nil unless args[:merge_user_username]
212
+ args[:milestone] = nil unless args[:milestone]
213
+ args[:my_reaction_emoji] = nil unless args[:my_reaction_emoji]
214
+ args[:non_archived] = nil unless args[:non_archived]
215
+ args[:order_by] = nil unless args[:order_by]
216
+ args[:project_id] = nil unless args[:project_id]
217
+ args[:reviewer_id] = nil unless args[:reviewer_id]
218
+ args[:reviewer_username] = nil unless args[:reviewer_username]
219
+ args[:scope] = nil unless args[:scope]
220
+ args[:search] = nil unless args[:search]
221
+ args[:sort] = nil unless args[:sort]
222
+ args[:source_branch] = nil unless args[:source_branch]
223
+ args[:state] = nil unless args[:state]
224
+ args[:target_branch] = nil unless args[:target_branch]
225
+ args[:updated_after] = nil unless args[:updated_after]
226
+ args[:updated_before] = nil unless args[:updated_before]
227
+ args[:limit] = 0 unless args[:limit]
228
+ params = ''
229
+ params += "approved=#{args[:approved]}&" unless args[:approved].nil?
230
+ params += "approved_by_ids=#{args[:approved_by_ids]}&" unless args[:approved_by_ids].nil?
231
+ params += "approved_by_usernames=#{args[:approved_by_usernames]}&" unless args[:approved_by_usernames].nil?
232
+ params += "approver_ids=#{args[:approver_ids]}&" unless args[:approver_ids].nil?
233
+ params += "assignee_id=#{args[:assignee_id]}&" unless args[:assignee_id].nil?
234
+ params += "author_id=#{args[:author_id]}&" unless args[:author_id].nil?
235
+ params += "author_username=#{args[:author_username]}&" unless args[:author_username].nil?
236
+ params += "created_after=#{args[:created_after]}&" unless args[:created_after].nil?
237
+ params += "created_before=#{args[:created_before]}&" unless args[:created_before].nil?
238
+ params += "labels=#{args[:labels]}&" unless args[:labels].nil?
239
+ params += "merge_user_id=#{args[:merge_user_id]}&" unless args[:merge_user_id].nil?
240
+ params += "merge_user_username=#{args[:merge_user_username]}&" unless args[:merge_user_username].nil?
241
+ params += "milestone=#{args[:milestone]}&" unless args[:milestone].nil?
242
+ params += "my_reaction_emoji=#{args[:my_reaction_emoji]}&" unless args[:my_reaction_emoji].nil?
243
+ params += "non_archived=#{args[:non_archived]}&" unless args[:non_archived].nil?
244
+ params += "order_by=#{args[:order_by]}&" unless args[:order_by].nil?
245
+ params += "project_id=#{args[:project_id]}&" unless args[:project_id].nil?
246
+ params += "reviewer_id=#{args[:reviewer_id]}&" unless args[:reviewer_id].nil?
247
+ params += "reviewer_username=#{args[:reviewer_username]}&" unless args[:reviewer_username].nil?
248
+ params += "scope=#{args[:scope]}&" unless args[:scope].nil?
249
+ params += "search=#{args[:search]}&" unless args[:search].nil?
250
+ params += "sort=#{args[:sort]}&" unless args[:sort].nil?
251
+ params += "source_branch=#{args[:source_branch]}&" unless args[:source_branch].nil?
252
+ params += "state=#{args[:state]}&" unless args[:state].nil?
253
+ params += "target_branch=#{args[:target_branch]}&" unless args[:target_branch].nil?
254
+ params += "updated_after=#{args[:updated_after]}&" unless args[:updated_after].nil?
255
+ params += "updated_before=#{args[:updated_before]}&" unless args[:updated_before].nil?
256
+ array = []
257
+ page = 1
258
+ base_url = if args[:project_id].nil?
259
+ "merge_requests"
260
+ else
261
+ "projects/#{args[:project_id]}/merge_requests"
262
+ end
263
+ loop do
264
+ response = client.connection.get("#{base_url}?#{params}&page=#{page}&per_page=100")
265
+ body = Oj.load(response.body)
266
+ array += body.map { |m| MergeRequests.new(m) }
267
+ break if args[:limit].to_i.positive? && array.count >= args[:limit].to_i
268
+ break if body.count < 100
269
+
270
+ page += 1
271
+ end
272
+ return array if args[:limit].to_i.zero?
273
+
274
+ array.first(args[:limit].to_i)
275
+ end
276
+
277
+ ##
278
+ # Locates a specific merge request in the GitLab system
279
+ #
280
+ # @author Jason Colyer
281
+ # @since 1.0.0
282
+ # @see
283
+ # https://docs.gitlab.com/api/merge_requests/#get-single-mr
284
+ # GitLab API > Merge requests > Get single MR
285
+ # @see SupportOps::GitLab::Configuration Setting up a client
286
+ # @example
287
+ # require 'support_ops_gitlab'
288
+ #
289
+ # SupportOps::GitLab::Configuration.configure do |config|
290
+ # config.url = 'https://gitlab.com/api/v4'
291
+ # config.token = 'abc123'
292
+ # end
293
+ #
294
+ # mr = SupportOps::GitLab::MergeRequests.get(987654)
295
+ # pp mr.title
296
+ # # => "Awesome merge request"
297
+ # pp mr.id
298
+ # # => 28
299
+ # pp mr.project_id
300
+ # # => 123456
301
+ # @example
302
+ # require 'support_ops_gitlab'
303
+ #
304
+ # SupportOps::GitLab::Configuration.configure do |config|
305
+ # config.url = 'https://gitlab.com/api/v4'
306
+ # config.token = 'abc123'
307
+ # end
308
+ #
309
+ # mr = SupportOps::GitLab::MergeRequests.get(iid: 28, project_id: 123456)
310
+ # pp mr.title
311
+ # # => "Awesome merge request"
312
+ # pp mr.id
313
+ # # => 987654
314
+ def self.get(object)
315
+ if object.is_a? MergeRequests
316
+ MergeRequests.new(id: id).find
317
+ elsif object.is_a? Hash
318
+ MergeRequests.new({ id: object[:id], iid: object[:iid], project_id: object[:project_id] }).find
319
+ else
320
+ MergeRequests.new(id: object).find
321
+ end
322
+ end
323
+
324
+ ##
325
+ # Locates a specific merge request in the GitLab system
326
+ #
327
+ # @author Jason Colyer
328
+ # @since 1.0.0
329
+ # @see
330
+ # https://docs.gitlab.com/api/merge_requests/#get-single-mr
331
+ # GitLab API > Merge requests > Get single MR
332
+ # @see SupportOps::GitLab::Configuration Setting up a client
333
+ # @example
334
+ # require 'support_ops_gitlab'
335
+ #
336
+ # SupportOps::GitLab::Configuration.configure do |config|
337
+ # config.url = 'https://gitlab.com/api/v4'
338
+ # config.token = 'abc123'
339
+ # end
340
+ #
341
+ # mr = SupportOps::GitLab::MergeRequests.get!(987654)
342
+ # pp mr.title
343
+ # # => "Awesome merge request"
344
+ # pp mr.id
345
+ # # => 28
346
+ # pp mr.project_id
347
+ # # => 123456
348
+ # @example
349
+ # require 'support_ops_gitlab'
350
+ #
351
+ # SupportOps::GitLab::Configuration.configure do |config|
352
+ # config.url = 'https://gitlab.com/api/v4'
353
+ # config.token = 'abc123'
354
+ # end
355
+ #
356
+ # mr = SupportOps::GitLab::MergeRequests.get!(iid: 28, project_id: 123456)
357
+ # pp mr.title
358
+ # # => "Awesome merge request"
359
+ # pp mr.id
360
+ # # => 987654
361
+ def self.get!(object)
362
+ if object.is_a? MergeRequests
363
+ MergeRequests.new(id: id).find!
364
+ elsif object.is_a? Hash
365
+ MergeRequests.new({ id: object[:id], iid: object[:iid], project_id: object[:project_id] }).find!
366
+ else
367
+ MergeRequests.new(id: object).find!
368
+ end
369
+ end
370
+
371
+ private
372
+
373
+ ##
374
+ # @private
375
+ def get_record
376
+ raise "Cannot locate merge request based off provided info" if self.id.nil? && (self.iid.nil? || self.project_id.nil?)
377
+ base_url = if self.id.nil?
378
+ "projects/#{self.project_id}/merge_requests/#{self.iid}"
379
+ else
380
+ "merge_requests/#{self.id}"
381
+ end
382
+ response = self.client.connection.get(base_url)
383
+ return nil if response.status != 200
384
+
385
+ Oj.load(response.body)
386
+ end
387
+
388
+ ##
389
+ # @private
390
+ def subscribe_record
391
+ response = self.client.connection.post("projects/#{self.project_id}/merge_requests/#{self.iid}/subscribe")
392
+ raise "Unable to subscribe to issue #{self.id} => #{body}" unless [201, 304].include? response.status
393
+ true
394
+ end
395
+
396
+ ##
397
+ # @private
398
+ def unsubscribe_record
399
+ response = self.client.connection.post("projects/#{self.project_id}/merge_requests/#{self.iid}/unsubscribe")
400
+ raise "Unable to unsubscribe to issue #{self.id} => #{body}" unless [201, 304].include? response.status
401
+ true
402
+ end
403
+
404
+ ##
405
+ # @private
406
+ def notes_record
407
+ Notes.list(type: 'MergeRequest', type_id: self.iid, project_id: self.project_id)
408
+ end
409
+ end
410
+ end
411
+ end
@@ -0,0 +1,195 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Defines the module SupportOps.
4
+ module SupportOps
5
+ # Defines the module GitLab
6
+ module GitLab
7
+ ##
8
+ # Defines the class Milestones within the module {SupportOps::GitLab}.
9
+ #
10
+ # @author Jason Colyer
11
+ # @since 1.0.0
12
+ # @attr [Array] add_labels Comma-separated label names to add to an issue
13
+ # @attr [String] created_at The date the milestone was created at
14
+ # @attr [String] description The description of the milestone
15
+ # @attr [String] due_date The date the milestone is due
16
+ # @attr [Boolean] expired If the milestone is expired or not
17
+ # @attr [Integer] group_id the ID of the group the milestone is in
18
+ # @attr [Integer] id The ID of the group milestone
19
+ # @attr [Integer] iid The internal ID of the milestone
20
+ # @attr [String] state The current state of the milestone
21
+ # @attr [String] state_event The state event of the milestone, close or activate (used for updated only)
22
+ # @attr [String] start_date The date the milestone starts on
23
+ # @attr [String] title The title of the milestone
24
+ # @attr [String] updated_at The date the milestone was last updated
25
+ # @attr [String] web_url The URL of the milestone
26
+ # @todo Get single milestone => https://docs.gitlab.com/api/group_milestones/#get-single-milestone
27
+ # @todo Get all burndown chart events for a single milestone => https://docs.gitlab.com/api/group_milestones/#get-all-burndown-chart-events-for-a-single-milestone
28
+ # @todo Document #save! (create/update)
29
+ # @todo Document #delete!
30
+ # @todo Document issues
31
+ # @todo Document merge_requests
32
+ class Milestones < SupportOps::GitLab::Base
33
+ define_attributes :created_at, :description, :due_date, :expired,
34
+ :group_id, :id, :iid, :state, :start_date, :title,
35
+ :updated_at, :web_url
36
+ readonly_attributes :created_at, :expired, :group_id, :id, :iid, :state,
37
+ :updated_at, :web_url
38
+
39
+ ##
40
+ # Lists all milestones for a group
41
+ #
42
+ # @author Jason Colyer
43
+ # @since 1.0.0
44
+ # @overload list(key: value)
45
+ # @param group_id [Integer required] The group to look within
46
+ # @param end_date [String optional] Return only milestones where
47
+ # start_date <= the provided end_date
48
+ # @param containing_date [String optional] Return only milestones where
49
+ # start_date <= containing_date <= due_date
50
+ # @param iids [Array optional] Return only the milestones having the
51
+ # given iid
52
+ # @param include_ancestors [xxx optional] Include milestones for all
53
+ # parent groups
54
+ # @param include_descendants [xxx optional] Include milestones for group
55
+ # and its descendants
56
+ # @param search [String optional] Return only milestones with a title or
57
+ # description matching the provided string (case-insensitive)
58
+ # @param search_title [xxx optional] Return only milestones with a title
59
+ # matching the provided string (case-insensitive); multiple terms can
60
+ # be provided, separated by an escaped space, either + or %20, and
61
+ # will be ANDed together; example: 17.4+17.5 will match substrings
62
+ # 17.4 and 17.5 (in any order)
63
+ # @param start_date [String optional] Return only milestones where
64
+ # due_date >= the provided start_date
65
+ # @param state [String optional] Return only active or closed milestones
66
+ # @param title [String optional] Return only the milestones having the
67
+ # given title (case-sensitive)
68
+ # @param updated_after [String optional] Return only milestones updated
69
+ # after the given datetime
70
+ # @param updated_before [String optional] Return only milestones updated
71
+ # before the given datetime
72
+ # @return [Array]
73
+ # @see
74
+ # https://docs.gitlab.com/api/group_milestones/#list-group-milestones
75
+ # GitLab API > Milestones > List group milestones
76
+ # @see SupportOps::GitLab::Configuration Setting up a client
77
+ # @example
78
+ # require 'support_ops_gitlab'
79
+ #
80
+ # SupportOps::GitLab::Configuration.configure do |config|
81
+ # config.url = 'https://gitlab.example.com/api/v4'
82
+ # config.token = 'abc123'
83
+ # end
84
+ #
85
+ # milestones = SupportOps::GitLab::Milestones.list(group_id: 123456)
86
+ # pp milestones.count
87
+ # # => 30
88
+ # pp milestones.last.due_date
89
+ # # => "2018-07-31"
90
+ def self.list(**args)
91
+ args[:group_id] = nil unless args[:group_id]
92
+ raise 'You have to provide a group_id' if args[:group_id].nil?
93
+ args[:group_id] = nil unless args[:group_id]
94
+ args[:end_date] = nil unless args[:end_date]
95
+ args[:containing_date] = nil unless args[:containing_date]
96
+ args[:iids] = nil unless args[:iids]
97
+ args[:include_ancestors] = nil unless args[:include_ancestors]
98
+ args[:include_descendants] = nil unless args[:include_descendants]
99
+ args[:search] = nil unless args[:search]
100
+ args[:search_title] = nil unless args[:search_title]
101
+ args[:start_date] = nil unless args[:start_date]
102
+ args[:state] = nil unless args[:state]
103
+ args[:title] = nil unless args[:title]
104
+ args[:updated_after] = nil unless args[:updated_after]
105
+ args[:updated_before] = nil unless args[:updated_before]
106
+ params = ''
107
+ params += "end_date=#{args[:end_date]}&" unless args[:end_date].nil?
108
+ params += "containing_date=#{args[:containing_date]}&" unless args[:containing_date].nil?
109
+ params += "iids=#{args[:iids]}&" unless args[:iids].nil?
110
+ params += "include_ancestors=#{args[:include_ancestors]}&" unless args[:include_ancestors].nil?
111
+ params += "include_descendants=#{args[:include_descendants]}&" unless args[:include_descendants].nil?
112
+ params += "search=#{args[:search]}&" unless args[:search].nil?
113
+ params += "search_title=#{args[:search_title]}&" unless args[:search_title].nil?
114
+ params += "start_date=#{args[:start_date]}&" unless args[:start_date].nil?
115
+ params += "state=#{args[:state]}&" unless args[:state].nil?
116
+ params += "title=#{args[:title]}&" unless args[:title].nil?
117
+ params += "updated_after=#{args[:updated_after]}&" unless args[:updated_after].nil?
118
+ params += "updated_before=#{args[:updated_before]}&" unless args[:updated_before].nil?
119
+ array = []
120
+ page = 1
121
+ loop do
122
+ response = client.connection.get("groups/#{args[:group_id]}/milestones?#{params}&page=#{page}&per_page=100")
123
+ body = Oj.load(response.body)
124
+ array += body.map { |m| Milestones.new(m) }
125
+ break if body.count < 100
126
+
127
+ page += 1
128
+ end
129
+ array
130
+ end
131
+
132
+ private
133
+
134
+ ##
135
+ # @private
136
+ def create_record
137
+ response = self.client.connection.post("groups/#{self.group_id}/milestones", attributes_for_save.to_json)
138
+ body = Oj.load(response.body)
139
+ raise "Failed to create milestone => #{body}" if response.status != 201
140
+ body
141
+ end
142
+
143
+ ##
144
+ # @private
145
+ def update_record
146
+ raise "Failed to update milestone => You didn't change anything in the object" if attributes_for_save.keys == [:id]
147
+ response = self.client.connection.put("groups/#{self.group_id}/milestones/#{self.iid}", attributes_for_save.to_json)
148
+ body = Oj.load(response.body)
149
+ raise "Failed to update milestone #{self.id} => #{body}" if response.status != 200
150
+ body
151
+ end
152
+
153
+ ##
154
+ # @private
155
+ def delete_record
156
+ response = self.client.connection.delete("groups/#{self.group_id}/milestones/#{self.iid}")
157
+ body = Oj.load(response.body)
158
+ raise "Failed to delete milestone #{self.id} => #{body}" unless response.status == 204
159
+ true
160
+ end
161
+
162
+ ##
163
+ # @private
164
+ def issues_record
165
+ array = []
166
+ page = 1
167
+ loop do
168
+ response = client.connection.get("groups/#{self.group_id}/milestones/#{self.id}/issues?page=#{page}&per_page=100")
169
+ body = Oj.load(response.body)
170
+ array += body.map { |i| Issues.new(i) }
171
+ break if body.count < 100
172
+
173
+ page += 1
174
+ end
175
+ array
176
+ end
177
+
178
+ ##
179
+ # @private
180
+ def merge_requests_record
181
+ array = []
182
+ page = 1
183
+ loop do
184
+ response = self.client.connection.get("groups/#{self.group_id}/milestones/#{self.id}/merge_requests?page=#{page}&per_page=100")
185
+ body = Oj.load(response.body)
186
+ array += body.map { |m| MergeRequests.new(m) }
187
+ break if body.count < 100
188
+
189
+ page += 1
190
+ end
191
+ array
192
+ end
193
+ end
194
+ end
195
+ end