jira-ruby 3.0.0 → 3.2.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 (34) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/CI.yml +1 -0
  3. data/.github/workflows/rubocop.yml +1 -1
  4. data/README.md +0 -1
  5. data/jira-ruby.gemspec +2 -1
  6. data/lib/jira/atlassian/jwt.rb +76 -0
  7. data/lib/jira/base_factory.rb +1 -1
  8. data/lib/jira/client.rb +10 -2
  9. data/lib/jira/jwt_client.rb +2 -2
  10. data/lib/jira/resource/attachment.rb +17 -2
  11. data/lib/jira/resource/comment.rb +12 -0
  12. data/lib/jira/resource/createmeta.rb +4 -4
  13. data/lib/jira/resource/issue.rb +52 -18
  14. data/lib/jira/resource/properties.rb +56 -0
  15. data/lib/jira/resource/worklog.rb +12 -0
  16. data/lib/jira/version.rb +1 -1
  17. data/lib/jira-ruby.rb +1 -0
  18. data/spec/data/files/jwt-signed-urls.json +317 -0
  19. data/spec/integration/issue_spec.rb +1 -2
  20. data/spec/integration/properties_spec.rb +45 -0
  21. data/spec/integration/transition_spec.rb +3 -2
  22. data/spec/integration/webhook_spec.rb +4 -2
  23. data/spec/jira/atlassian/jwt_spec.rb +60 -0
  24. data/spec/jira/resource/issue_spec.rb +39 -1
  25. data/spec/mock_responses/issue/10002/properties/foo.json +4 -0
  26. data/spec/mock_responses/issue/10002/properties/xyz.json +4 -0
  27. data/spec/mock_responses/issue/10002/properties/xyz.put.json +4 -0
  28. data/spec/mock_responses/issue/10002/properties.json +12 -0
  29. data/spec/support/clients_helper.rb +3 -3
  30. data/spec/support/shared_examples/integration.rb +34 -38
  31. metadata +27 -6
  32. data/spec/mock_responses/jira/rest/webhooks/1.0/webhook.json +0 -11
  33. data/spec/mock_responses/webhook/webhook.json +0 -11
  34. /data/spec/mock_responses/{jira/rest/webhooks/1.0/webhook → webhook}/2.json +0 -0
@@ -1,20 +1,18 @@
1
1
  require 'cgi'
2
2
 
3
- def get_mock_from_path(method, options = {})
4
- prefix = if defined? belongs_to
5
- "#{belongs_to.path_component}/"
6
- else
7
- ''
8
- end
9
-
10
- url = if options[:url]
11
- options[:url]
12
- elsif options[:key]
13
- described_class.singular_path(client, options[:key], prefix)
14
- else
15
- described_class.collection_path(client, prefix)
16
- end
17
- file_path = url.sub(client.options[:rest_base_path], '')
3
+ def build_url(options = {})
4
+ prefix = defined?(belongs_to) ? "#{belongs_to.path_component}/" : '/'
5
+ path = if options.key?(:key)
6
+ described_class.singular_path(client, options[:key], prefix)
7
+ else
8
+ described_class.collection_path(client, prefix)
9
+ end
10
+ site_url + path
11
+ end
12
+
13
+ def get_mock_from_url(method, url, options = {})
14
+ # Remove site_url and rest api portion of the url
15
+ file_path = url.sub(site_url + client.options[:rest_base_path], '')
18
16
  file_path = "#{file_path}.#{options[:suffix]}" if options[:suffix]
19
17
  file_path = "#{file_path}.#{method}" unless method == :get
20
18
  value_if_not_found = options.key?(:value_if_not_found) ? options[:value_if_not_found] : false
@@ -63,8 +61,8 @@ end
63
61
 
64
62
  shared_examples 'a resource with a collection GET endpoint' do
65
63
  it 'gets the collection' do
66
- stub_request(:get, site_url + described_class.collection_path(client))
67
- .to_return(status: 200, body: get_mock_from_path(:get))
64
+ req_url = build_url
65
+ stub_request(:get, req_url).to_return(status: 200, body: get_mock_from_url(:get, req_url))
68
66
  collection = build_receiver.all
69
67
 
70
68
  expect(collection.length).to eq(expected_collection_length)
@@ -74,10 +72,8 @@ end
74
72
 
75
73
  shared_examples 'a resource with JQL inputs and a collection GET endpoint' do
76
74
  it 'gets the collection' do
77
- stub_request(
78
- :get,
79
- "#{site_url}#{client.options[:rest_base_path]}/search/jql?jql=#{CGI.escape(jql_query_string)}"
80
- ).to_return(status: 200, body: get_mock_response('issue.json'))
75
+ req_url = "#{site_url}#{client.options[:rest_base_path]}/search/jql?jql=#{CGI.escape(jql_query_string)}"
76
+ stub_request(:get, req_url).to_return(status: 200, body: get_mock_response('issue.json'))
81
77
 
82
78
  collection = build_receiver.jql(jql_query_string)
83
79
 
@@ -90,8 +86,8 @@ shared_examples 'a resource with a singular GET endpoint' do
90
86
  it 'GETs a single resource' do
91
87
  # E.g., for JIRA::Resource::Project, we need to call
92
88
  # client.Project.find()
93
- stub_request(:get, site_url + described_class.singular_path(client, key, prefix))
94
- .to_return(status: 200, body: get_mock_from_path(:get, key:))
89
+ req_url = build_url(key:)
90
+ stub_request(:get, req_url).to_return(status: 200, body: get_mock_from_url(:get, req_url))
95
91
  subject = client.send(class_basename).find(key, options)
96
92
 
97
93
  expect(subject).to have_attributes(expected_attributes)
@@ -100,8 +96,8 @@ shared_examples 'a resource with a singular GET endpoint' do
100
96
  it 'builds and fetches a single resource' do
101
97
  # E.g., for JIRA::Resource::Project, we need to call
102
98
  # client.Project.build('key' => 'ABC123')
103
- stub_request(:get, site_url + described_class.singular_path(client, key, prefix))
104
- .to_return(status: 200, body: get_mock_from_path(:get, key:))
99
+ req_url = build_url(key:)
100
+ stub_request(:get, req_url).to_return(status: 200, body: get_mock_from_url(:get, req_url))
105
101
 
106
102
  subject = build_receiver.build(described_class.key_attribute.to_s => key)
107
103
  subject.fetch
@@ -110,7 +106,7 @@ shared_examples 'a resource with a singular GET endpoint' do
110
106
  end
111
107
 
112
108
  it 'handles a 404' do
113
- stub_request(:get, site_url + described_class.singular_path(client, '99999', prefix))
109
+ stub_request(:get, build_url(key: '99999'))
114
110
  .to_return(status: 404, body: "{\"errorMessages\":[\"#{class_basename} Does Not Exist\"],\"errors\": {}}")
115
111
  expect do
116
112
  client.send(class_basename).find('99999', options)
@@ -122,8 +118,8 @@ shared_examples 'a resource with a DELETE endpoint' do
122
118
  it 'deletes a resource' do
123
119
  # E.g., for JIRA::Resource::Project, we need to call
124
120
  # client.Project.delete()
125
- stub_request(:delete, site_url + described_class.singular_path(client, key, prefix))
126
- .to_return(status: 204, body: nil)
121
+ req_url = build_url(key:)
122
+ stub_request(:delete, req_url).to_return(status: 204, body: nil)
127
123
 
128
124
  subject = build_receiver.build(described_class.key_attribute.to_s => key)
129
125
  expect(subject.delete).to be_truthy
@@ -132,8 +128,8 @@ end
132
128
 
133
129
  shared_examples 'a resource with a POST endpoint' do
134
130
  it 'saves a new resource' do
135
- stub_request(:post, site_url + described_class.collection_path(client, prefix))
136
- .to_return(status: 201, body: get_mock_from_path(:post))
131
+ req_url = build_url
132
+ stub_request(:post, req_url).to_return(status: 201, body: get_mock_from_url(:post, req_url))
137
133
  subject = build_receiver.build
138
134
  expect(subject.save(attributes_for_post)).to be_truthy
139
135
  expected_attributes_from_post.each do |method_name, value|
@@ -144,10 +140,10 @@ end
144
140
 
145
141
  shared_examples 'a resource with a PUT endpoint' do
146
142
  it 'saves an existing component' do
147
- stub_request(:get, site_url + described_class.singular_path(client, key, prefix))
148
- .to_return(status: 200, body: get_mock_from_path(:get, key:))
149
- stub_request(:put, site_url + described_class.singular_path(client, key, prefix))
150
- .to_return(status: 200, body: get_mock_from_path(:put, key:, value_if_not_found: nil))
143
+ req_url = build_url(key:)
144
+ stub_request(:get, req_url).to_return(status: 200, body: get_mock_from_url(:get, req_url))
145
+ stub_request(:put, req_url)
146
+ .to_return(status: 200, body: get_mock_from_url(:put, req_url, value_if_not_found: nil))
151
147
  subject = build_receiver.build(described_class.key_attribute.to_s => key)
152
148
  subject.fetch
153
149
  expect(subject.save(attributes_for_put)).to be_truthy
@@ -159,10 +155,10 @@ end
159
155
 
160
156
  shared_examples 'a resource with a PUT endpoint that rejects invalid fields' do
161
157
  it 'fails to save with an invalid field' do
162
- stub_request(:get, site_url + described_class.singular_path(client, key))
163
- .to_return(status: 200, body: get_mock_from_path(:get, key:))
164
- stub_request(:put, site_url + described_class.singular_path(client, key))
165
- .to_return(status: 400, body: get_mock_from_path(:put, key:, suffix: 'invalid'))
158
+ req_url = build_url(key:)
159
+ stub_request(:get, req_url).to_return(status: 200, body: get_mock_from_url(:get, req_url))
160
+ stub_request(:put, req_url)
161
+ .to_return(status: 400, body: get_mock_from_url(:put, req_url, suffix: 'invalid'))
166
162
  subject = client.send(class_basename).build(described_class.key_attribute.to_s => key)
167
163
  subject.fetch
168
164
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jira-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0
4
+ version: 3.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - SUMO Heavy Industries
8
8
  - test IO
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-09-15 00:00:00.000000000 Z
11
+ date: 2026-05-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -25,7 +25,7 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: atlassian-jwt
28
+ name: cgi
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: jwt
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '2.1'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '2.1'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: multipart-post
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -87,6 +101,7 @@ files:
87
101
  - Rakefile
88
102
  - jira-ruby.gemspec
89
103
  - lib/jira-ruby.rb
104
+ - lib/jira/atlassian/jwt.rb
90
105
  - lib/jira/base.rb
91
106
  - lib/jira/base_factory.rb
92
107
  - lib/jira/client.rb
@@ -115,6 +130,7 @@ files:
115
130
  - lib/jira/resource/issuetype.rb
116
131
  - lib/jira/resource/priority.rb
117
132
  - lib/jira/resource/project.rb
133
+ - lib/jira/resource/properties.rb
118
134
  - lib/jira/resource/rapidview.rb
119
135
  - lib/jira/resource/remotelink.rb
120
136
  - lib/jira/resource/resolution.rb
@@ -131,6 +147,7 @@ files:
131
147
  - lib/jira/resource/worklog.rb
132
148
  - lib/jira/version.rb
133
149
  - lib/tasks/generate.rake
150
+ - spec/data/files/jwt-signed-urls.json
134
151
  - spec/data/files/short.txt
135
152
  - spec/integration/attachment_spec.rb
136
153
  - spec/integration/comment_spec.rb
@@ -141,6 +158,7 @@ files:
141
158
  - spec/integration/issuetype_spec.rb
142
159
  - spec/integration/priority_spec.rb
143
160
  - spec/integration/project_spec.rb
161
+ - spec/integration/properties_spec.rb
144
162
  - spec/integration/rapidview_spec.rb
145
163
  - spec/integration/resolution_spec.rb
146
164
  - spec/integration/status_category_spec.rb
@@ -151,6 +169,7 @@ files:
151
169
  - spec/integration/watcher_spec.rb
152
170
  - spec/integration/webhook_spec.rb
153
171
  - spec/integration/worklog_spec.rb
172
+ - spec/jira/atlassian/jwt_spec.rb
154
173
  - spec/jira/base_factory_spec.rb
155
174
  - spec/jira/base_spec.rb
156
175
  - spec/jira/client_spec.rb
@@ -194,6 +213,10 @@ files:
194
213
  - spec/mock_responses/issue/10002/comment.post.json
195
214
  - spec/mock_responses/issue/10002/comment/10000.json
196
215
  - spec/mock_responses/issue/10002/comment/10000.put.json
216
+ - spec/mock_responses/issue/10002/properties.json
217
+ - spec/mock_responses/issue/10002/properties/foo.json
218
+ - spec/mock_responses/issue/10002/properties/xyz.json
219
+ - spec/mock_responses/issue/10002/properties/xyz.put.json
197
220
  - spec/mock_responses/issue/10002/transitions.json
198
221
  - spec/mock_responses/issue/10002/transitions.post.json
199
222
  - spec/mock_responses/issue/10002/watchers.json
@@ -205,8 +228,6 @@ files:
205
228
  - spec/mock_responses/issueLinkType/10000.json
206
229
  - spec/mock_responses/issuetype.json
207
230
  - spec/mock_responses/issuetype/5.json
208
- - spec/mock_responses/jira/rest/webhooks/1.0/webhook.json
209
- - spec/mock_responses/jira/rest/webhooks/1.0/webhook/2.json
210
231
  - spec/mock_responses/priority.json
211
232
  - spec/mock_responses/priority/1.json
212
233
  - spec/mock_responses/project.json
@@ -230,7 +251,7 @@ files:
230
251
  - spec/mock_responses/version/10000.json
231
252
  - spec/mock_responses/version/10000.put.json
232
253
  - spec/mock_responses/webhook.json
233
- - spec/mock_responses/webhook/webhook.json
254
+ - spec/mock_responses/webhook/2.json
234
255
  - spec/spec_helper.rb
235
256
  - spec/support/clients_helper.rb
236
257
  - spec/support/matchers/have_attributes.rb
@@ -1,11 +0,0 @@
1
- [{"name":"from API",
2
- "url":"http://localhost:3000/webhooks/1",
3
- "excludeBody":false,
4
- "filters":{"issue-related-events-section":""},
5
- "events":[],
6
- "enabled":true,
7
- "self":"http://localhost:2990/jira/rest/webhooks/1.0/webhook/2",
8
- "lastUpdatedUser":"admin",
9
- "lastUpdatedDisplayName":"admin",
10
- "lastUpdated":1453306520188
11
- }]
@@ -1,11 +0,0 @@
1
- {"name":"from API",
2
- "url":"http://localhost:3000/webhooks/1",
3
- "excludeBody":false,
4
- "filters":{"issue-related-events-section":""},
5
- "events":[],
6
- "enabled":true,
7
- "self":"http://localhost:2990/jira/rest/webhooks/1.0/webhook/2",
8
- "lastUpdatedUser":"admin",
9
- "lastUpdatedDisplayName":"admin",
10
- "lastUpdated":1453306520188
11
- }