rujira 0.3.4 → 0.4.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.
@@ -1,12 +1,18 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'issue/watchers'
4
+ require_relative 'issue/comments'
5
+
3
6
  module Rujira
4
7
  module Api
5
8
  # Provides access to Jira issues via the REST API.
6
9
  # API reference:
7
10
  # https://docs.atlassian.com/software/jira/docs/api/REST/9.17.0/#api/2/issue
8
11
  #
9
- class Issue < Common
12
+ class Issue < Common # rubocop:disable Metrics/ClassLength
13
+ include Watchers
14
+ include Comments
15
+
10
16
  # Creates a new issue.
11
17
  #
12
18
  # @yield [builder] Optional block to configure the request payload.
@@ -31,6 +37,28 @@ module Rujira
31
37
  run
32
38
  end
33
39
 
40
+ # Creates multiple issues in bulk.
41
+ #
42
+ # @yield [builder] Block to configure the payload for bulk creation.
43
+ # @return [Object] The API response after creating issues.
44
+ #
45
+ # @example Create issues in bulk
46
+ # client.Issue.create_bulk do
47
+ # payload issues: [
48
+ # { fields: { project: { key: "TEST" }, summary: "Issue 1", issuetype: { name: "Task" } } },
49
+ # { fields: { project: { key: "TEST" }, summary: "Issue 2", issuetype: { name: "Bug" } } }
50
+ # ]
51
+ # end
52
+ #
53
+ def create_bulk(&block)
54
+ builder do
55
+ path 'issue/bulk'
56
+ method :post
57
+ instance_eval(&block) if block_given?
58
+ end
59
+ run
60
+ end
61
+
34
62
  # Retrieves an issue by its ID or key.
35
63
  #
36
64
  # @param [String] id_or_key The issue ID or key.
@@ -91,57 +119,315 @@ module Rujira
91
119
  run
92
120
  end
93
121
 
94
- # Adds a comment to an issue.
122
+ # Archives an issue by its ID or key.
95
123
  #
96
124
  # @param [String] id_or_key The issue ID or key.
97
- # @yield [builder] Optional block to configure the comment payload.
98
- # @return [Object] The API response containing the created comment.
125
+ # @return [Object] The API response after archiving the issue.
126
+ #
127
+ # @example Archive an issue
128
+ # client.Issue.archive("TEST-123")
99
129
  #
100
- # @example Add a comment
101
- # client.Issue.comment("TEST-123") do
102
- # payload body: "This is a comment"
130
+ def archive(id_or_key)
131
+ abort 'Issue ID or KEY is required' if id_or_key.to_s.strip.empty?
132
+ builder do
133
+ path "issue/#{id_or_key}/archive"
134
+ method :put
135
+ end
136
+ run
137
+ end
138
+
139
+ # Retrieves the archive information for a given issue.
140
+ #
141
+ # @param [String] id_or_key The issue ID or key.
142
+ # @return [Object] The API response containing archive details for the issue.
143
+ #
144
+ # @example List archive information for an issue
145
+ # client.Issue.list_archive("TEST-123")
146
+ def list_archive(id_or_key)
147
+ abort 'Issue ID or KEY is required' if id_or_key.to_s.strip.empty?
148
+ builder do
149
+ path "issue/#{id_or_key}/archive"
150
+ end
151
+ run
152
+ end
153
+
154
+ # Updates the assignee of an issue.
155
+ #
156
+ # @param [String] id_or_key The issue ID or key.
157
+ # @yield [builder] Block to configure the payload for assignee update.
158
+ # @return [Object] The API response after updating the assignee.
159
+ #
160
+ # @example Assign an issue to a user
161
+ # client.Issue.assignee("TEST-123") do
162
+ # payload name: "john.doe"
103
163
  # end
104
164
  #
105
- def comment(id_or_key, &block)
165
+ def assignee(id_or_key)
106
166
  abort 'Issue ID or KEY is required' if id_or_key.to_s.strip.empty?
107
- @client.Comment.create id_or_key, &block
167
+ builder do
168
+ path "issue/#{id_or_key}/assignee"
169
+ method :put
170
+ end
171
+ run
108
172
  end
109
173
 
110
- # Adds a watcher to an issue.
174
+ # Retrieves the edit metadata for a given issue.
175
+ # This provides information about which fields can be edited and their constraints.
111
176
  #
112
177
  # @param [String] id_or_key The issue ID or key.
113
- # @param [String] name The username to add as a watcher.
114
- # @yield [builder] Optional block to configure the request.
115
- # @return [Object] The API response after adding the watcher.
178
+ # @yield [builder] Optional block to configure additional request parameters.
179
+ # @return [Object] The API response containing edit metadata.
116
180
  #
117
- # @example Add a watcher
118
- # client.Issue.watchers("TEST-123", "johndoe")
181
+ # @example Get edit metadata for an issue
182
+ # client.Issue.editmeta("TEST-123") do
183
+ # # Optional: add query parameters or headers
184
+ # params expand: "projects,issuetypes.fields"
185
+ # end
186
+ def editmeta(id_or_key, &block)
187
+ abort 'Issue ID or KEY is required' if id_or_key.to_s.strip.empty?
188
+ builder do
189
+ path "issue/#{id_or_key}/editmeta"
190
+ instance_eval(&block) if block_given?
191
+ end
192
+ run
193
+ end
194
+
195
+ # Sends a notification about a specific issue.
119
196
  #
120
- def watchers(id_or_key, name, &block)
197
+ # @param [String] id_or_key The issue ID or key.
198
+ # @yield [builder] Block to configure the payload for the notification.
199
+ # @return [Object] The API response after sending the notification.
200
+ #
201
+ # @example Notify users about an issue
202
+ # client.Issue.notify("TEST-123") do
203
+ # payload {
204
+ # subject: "Issue Update",
205
+ # textBody: "The issue has been updated.",
206
+ # to: [{ type: "user", username: "john.doe" }]
207
+ # }
208
+ # end
209
+ def notify(id_or_key, &block)
121
210
  abort 'Issue ID or KEY is required' if id_or_key.to_s.strip.empty?
122
211
  builder do
123
- path "issue/#{id_or_key}/watchers"
124
212
  method :post
125
- payload name.to_json
213
+ path "issue/#{id_or_key}/notify"
126
214
  instance_eval(&block) if block_given?
127
215
  end
128
216
  run
129
217
  end
130
218
 
131
- # Uploads an attachment to an issue.
219
+ # Retrieves remote links for a given issue.
132
220
  #
133
221
  # @param [String] id_or_key The issue ID or key.
134
- # @param [String] path The local file path of the attachment.
135
- # @yield [builder] Optional block to configure the request.
136
- # @return [Object] The API response containing the uploaded attachment.
222
+ # @yield [builder] Optional block to configure additional request parameters.
223
+ # @return [Object] The API response containing remote links.
224
+ #
225
+ # @example Get remote links for an issue
226
+ # client.Issue.remotelink("TEST-123") do
227
+ # # Optional: add query parameters or headers
228
+ # params expand: "application"
229
+ # end
230
+ def remotelink(id_or_key, &block)
231
+ abort 'Issue ID or KEY is required' if id_or_key.to_s.strip.empty?
232
+ builder do
233
+ path "issue/#{id_or_key}/remotelink"
234
+ instance_eval(&block) if block_given?
235
+ end
236
+ run
237
+ end
238
+
239
+ # Creates a remote link for a given issue.
240
+ #
241
+ # @param [String] id_or_key The issue ID or key.
242
+ # @yield [builder] Block to configure the payload for the remote link.
243
+ # @return [Object] The API response after creating the remote link.
244
+ #
245
+ # @example Create a remote link for an issue
246
+ # client.Issue.create_remotelink("TEST-123") do
247
+ # payload {
248
+ # object: {
249
+ # url: "https://example.com/task/123",
250
+ # title: "External Task"
251
+ # }
252
+ # }
253
+ # end
254
+ def create_remotelink(id_or_key, &block)
255
+ abort 'Issue ID or KEY is required' if id_or_key.to_s.strip.empty?
256
+ builder do
257
+ method :post
258
+ path "issue/#{id_or_key}/remotelink"
259
+ instance_eval(&block) if block_given?
260
+ end
261
+ run
262
+ end
263
+
264
+ # Deletes remote links for a given issue.
137
265
  #
138
- # @example Upload an attachment
139
- # client.Issue.attachments("TEST-123", "/tmp/file.txt")
266
+ # @param [String] id_or_key The issue ID or key.
267
+ # @yield [builder] Optional block to configure additional request parameters.
268
+ # @return [Object] The API response after deleting the remote link(s).
140
269
  #
141
- def attachments(id_or_key, path, &block)
270
+ # @example Delete remote links for an issue
271
+ # client.Issue.delete_remotelink("TEST-123") do
272
+ # # Optional: add query parameters or headers if needed
273
+ # params globalId: "com.example:task-123"
274
+ # end
275
+ def delete_remotelink(id_or_key, &block)
142
276
  abort 'Issue ID or KEY is required' if id_or_key.to_s.strip.empty?
143
- @client.Attachments.create id_or_key, path, &block
277
+ builder do
278
+ method :delete
279
+ path "issue/#{id_or_key}/remotelink"
280
+ instance_eval(&block) if block_given?
281
+ end
282
+ run
283
+ end
284
+
285
+ # Retrieves a specific remote link for a given issue.
286
+ #
287
+ # @param [String] id_or_key The issue ID or key.
288
+ # @param [String] link_id The remote link ID.
289
+ # @yield [builder] Optional block to configure additional request parameters.
290
+ # @return [Object] The API response containing the remote link details.
291
+ #
292
+ # @example Get a specific remote link
293
+ # client.Issue.get_remotelink_by_id("TEST-123", "20001") do
294
+ # # Optional: add headers or query parameters
295
+ # end
296
+ def get_remotelink_by_id(id_or_key, link_id, &block)
297
+ abort 'Issue ID or KEY is required' if id_or_key.to_s.strip.empty?
298
+ builder do
299
+ path "issue/#{id_or_key}/remotelink/#{link_id}"
300
+ instance_eval(&block) if block_given?
301
+ end
302
+ run
303
+ end
304
+
305
+ # Updates a specific remote link for a given issue.
306
+ #
307
+ # @param [String] id_or_key The issue ID or key.
308
+ # @param [String] link_id The remote link ID.
309
+ # @yield [builder] Block to configure the payload for updating the remote link.
310
+ # @return [Object] The API response after updating the remote link.
311
+ #
312
+ # @example Update a specific remote link
313
+ # client.Issue.update_remotelink("TEST-123", "20001") do
314
+ # payload {
315
+ # object: {
316
+ # url: "https://example.com/updated-task/123",
317
+ # title: "Updated Task"
318
+ # }
319
+ # }
320
+ # end
321
+ def update_remotelink(id_or_key, link_id, &block)
322
+ abort 'Issue ID or KEY is required' if id_or_key.to_s.strip.empty?
323
+ builder do
324
+ method :put
325
+ path "issue/#{id_or_key}/remotelink/#{link_id}"
326
+ instance_eval(&block) if block_given?
327
+ end
328
+ run
329
+ end
330
+
331
+ # Deletes a specific remote link by its ID for a given issue.
332
+ #
333
+ # @param [String] id_or_key The issue ID or key.
334
+ # @param [String] link_id The remote link ID.
335
+ # @yield [builder] Optional block to configure additional request parameters.
336
+ # @return [Object] The API response after deleting the remote link.
337
+ #
338
+ # @example Delete a specific remote link
339
+ # client.Issue.delete_remotelink_by_id("TEST-123", "20001") do
340
+ # # Optional: add headers or query parameters
341
+ # end
342
+ def delete_remotelink_by_id(id_or_key, link_id, &block)
343
+ abort 'Issue ID or KEY is required' if id_or_key.to_s.strip.empty?
344
+ builder do
345
+ method :delete
346
+ path "issue/#{id_or_key}/remotelink/#{link_id}"
347
+ instance_eval(&block) if block_given?
348
+ end
349
+ run
350
+ end
351
+
352
+ # Restores a previously archived issue.
353
+ #
354
+ # @param [String] id_or_key The issue ID or key.
355
+ # @yield [builder] Optional block to configure additional request parameters.
356
+ # @return [Object] The API response after restoring the issue.
357
+ #
358
+ # @example Restore an issue
359
+ # client.Issue.restore("TEST-123") do
360
+ # # Optional: add headers or payload if needed
361
+ # end
362
+ def restore(id_or_key, &block)
363
+ abort 'Issue ID or KEY is required' if id_or_key.to_s.strip.empty?
364
+ builder do
365
+ method :put
366
+ path "issue/#{id_or_key}/restore"
367
+ instance_eval(&block) if block_given?
368
+ end
369
+ run
370
+ end
371
+
372
+ # Performs a transition on a given issue (e.g., change status).
373
+ #
374
+ # @param [String] id_or_key The issue ID or key.
375
+ # @yield [builder] Block to configure the payload for the transition.
376
+ # @return [Object] The API response after performing the transition.
377
+ #
378
+ # @example Transition an issue
379
+ # client.Issue.transitions("TEST-123") do
380
+ # payload transition: { id: "31" }
381
+ # end
382
+ def transitions(id_or_key, &block)
383
+ abort 'Issue ID or KEY is required' if id_or_key.to_s.strip.empty?
384
+ builder do
385
+ method :post
386
+ path "issue/#{id_or_key}/transitions"
387
+ instance_eval(&block) if block_given?
388
+ end
389
+ run
390
+ end
391
+
392
+ # Retrieves available transitions for a given issue.
393
+ #
394
+ # @param [String] id_or_key The issue ID or key.
395
+ # @yield [builder] Optional block to configure additional request parameters.
396
+ # @return [Object] The API response containing available transitions.
397
+ #
398
+ # @example Get available transitions
399
+ # client.Issue.get_transitions("TEST-123") do
400
+ # # Optional: add query parameters or headers
401
+ # end
402
+ def get_transitions(id_or_key, &block)
403
+ abort 'Issue ID or KEY is required' if id_or_key.to_s.strip.empty?
404
+ builder do
405
+ path "issue/#{id_or_key}/transitions"
406
+ instance_eval(&block) if block_given?
407
+ end
408
+ run
409
+ end
410
+
411
+ # Uploads a file as an attachment to the specified Jira issue.
412
+ #
413
+ # @param [String] id_or_key The issue ID or key to which the file will be attached.
414
+ # @param [String] path The local file path of the attachment to upload.
415
+ # @yield [builder] Optional block to customize the request builder.
416
+ # @return [Object] The API response after executing the request.
417
+ #
418
+ def create_attachments(id_or_key, path, &block)
419
+ abort 'Issue ID or KEY is required' if id_or_key.to_s.strip.empty?
420
+ client = @client
421
+ builder do
422
+ path "issue/#{id_or_key}/attachments"
423
+ method :post
424
+ headers 'X-Atlassian-Token': 'no-check'
425
+ payload file: client.file(path)
426
+ instance_eval(&block) if block_given?
427
+ end
428
+ run
144
429
  end
430
+ alias attachments create_attachments
145
431
  end
146
432
  end
147
433
  end
@@ -22,6 +22,42 @@ module Rujira
22
22
  end
23
23
  run
24
24
  end
25
+
26
+ # Updates the current user's profile.
27
+ #
28
+ # @yield [builder] Block to configure the payload or additional request parameters.
29
+ # @return [Object] The API response after updating the user profile.
30
+ #
31
+ # @example Update user profile
32
+ # client.Myself.update do
33
+ # payload({ displayName: "New Name", emailAddress: "new@example.com" })
34
+ # end
35
+ def update(&block)
36
+ builder do
37
+ method :put
38
+ path 'myself'
39
+ instance_eval(&block) if block_given?
40
+ end
41
+ run
42
+ end
43
+
44
+ # Changes the current user's password.
45
+ #
46
+ # @yield [builder] Block to configure the payload for the password change.
47
+ # @return [Object] The API response after changing the password.
48
+ #
49
+ # @example Change user password
50
+ # client.Myself.password do
51
+ # payload({ password: "newpassword123" })
52
+ # end
53
+ def password(&block)
54
+ builder do
55
+ method :put
56
+ path 'myself'
57
+ instance_eval(&block) if block_given?
58
+ end
59
+ run
60
+ end
25
61
  end
26
62
  end
27
63
  end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rujira
4
+ module Api
5
+ # Provides access to Jira permissions via the REST API.
6
+ # Allows listing all permission schemes available in Jira.
7
+ #
8
+ # API reference:
9
+ # https://docs.atlassian.com/software/jira/docs/api/REST/9.17.0/#api/2/permissions
10
+ #
11
+ class Permissions < Common
12
+ # Retrieves the list of all permissions in Jira.
13
+ #
14
+ # @yield [builder] Optional block to configure the request.
15
+ # @return [Object] The API response containing permissions details.
16
+ #
17
+ # @example List all permissions
18
+ # client.Permissions.list
19
+ #
20
+ def list
21
+ builder do
22
+ path 'permissions'
23
+ method :get
24
+ end
25
+ run
26
+ end
27
+
28
+ # Retrieves the list of my permissions in Jira.
29
+ #
30
+ # @yield [builder] Optional block to configure the request.
31
+ # @return [Object] The API response containing permissions details.
32
+ #
33
+ # @example List all permissions
34
+ # client.Permissions.my
35
+ #
36
+ def my
37
+ builder do
38
+ path 'mypermissions'
39
+ method :get
40
+ end
41
+ run
42
+ end
43
+ end
44
+ end
45
+ end
data/lib/rujira/client.rb CHANGED
@@ -23,6 +23,7 @@ module Rujira
23
23
  def initialize(url, debug: false)
24
24
  @uri = URI(url)
25
25
  @debug = ENV.fetch('RUJIRA_DEBUG', debug.to_s) == 'true'
26
+ @raise_error = false
26
27
  @request = Request.new
27
28
  end
28
29
 
@@ -80,7 +81,12 @@ module Rujira
80
81
 
81
82
  response = connection.public_send(@request.method, *args)
82
83
 
83
- response.success? ? response.body : (raise "Request failed with status #{response.status}")
84
+ if response.success?
85
+ response.body
86
+ else
87
+ (raise "Request failed with status #{response.status} " \
88
+ "and body #{response.body}")
89
+ end
84
90
  rescue StandardError => e
85
91
  raise "Error: #{e.class} - #{e.message}"
86
92
  end
@@ -96,7 +102,7 @@ module Rujira
96
102
  builder.request :multipart, flat_encode: true
97
103
  builder.request :json
98
104
  builder.response :json
99
- builder.response :raise_error
105
+ builder.response :raise_error if @raise_error
100
106
  builder.response :logger if @debug
101
107
  end
102
108
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rujira
4
- VERSION = '0.3.4'
4
+ VERSION = '0.4.0'
5
5
  end
data/lib/rujira.rb CHANGED
@@ -22,6 +22,14 @@ require_relative 'rujira/api/server_info'
22
22
  require_relative 'rujira/api/dashboard'
23
23
  require_relative 'rujira/api/board'
24
24
  require_relative 'rujira/api/sprint'
25
+ require_relative 'rujira/api/permissions'
26
+ require_relative 'rujira/api/application_properties'
27
+ require_relative 'rujira/api/applicationrole'
28
+ require_relative 'rujira/api/avatar'
29
+ require_relative 'rujira/api/configuration'
30
+ require_relative 'rujira/api/custom_fields'
31
+ require_relative 'rujira/api/field'
32
+ require_relative 'rujira/api/filter'
25
33
 
26
34
  # Main Rujira module.
27
35
  # Serves as the namespace for the Jira SDK.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rujira
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.4
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrey Semenov
@@ -55,13 +55,23 @@ files:
55
55
  - contrib/jira_link_generator.rb
56
56
  - examples/create_issue_in_sprint.rb
57
57
  - lib/rujira.rb
58
+ - lib/rujira/api/application_properties.rb
59
+ - lib/rujira/api/applicationrole.rb
58
60
  - lib/rujira/api/attachments.rb
61
+ - lib/rujira/api/avatar.rb
59
62
  - lib/rujira/api/board.rb
60
63
  - lib/rujira/api/comment.rb
61
64
  - lib/rujira/api/common.rb
65
+ - lib/rujira/api/configuration.rb
66
+ - lib/rujira/api/custom_fields.rb
62
67
  - lib/rujira/api/dashboard.rb
68
+ - lib/rujira/api/field.rb
69
+ - lib/rujira/api/filter.rb
63
70
  - lib/rujira/api/issue.rb
71
+ - lib/rujira/api/issue/comments.rb
72
+ - lib/rujira/api/issue/watchers.rb
64
73
  - lib/rujira/api/myself.rb
74
+ - lib/rujira/api/permissions.rb
65
75
  - lib/rujira/api/project.rb
66
76
  - lib/rujira/api/search.rb
67
77
  - lib/rujira/api/server_info.rb