rujira 0.7.0 → 0.7.3
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +33 -49
- data/README.md +131 -1
- data/Rakefile +0 -8
- data/cliff.toml +3 -0
- data/compose.yaml +1 -1
- data/examples/create_issue_as_obj.rb +1 -1
- data/examples/create_issue_in_sprint.rb +1 -1
- data/lib/rujira/api/board.rb +140 -1
- data/lib/rujira/api/common.rb +11 -5
- data/lib/rujira/api/issue_type.rb +24 -0
- data/lib/rujira/api/priority.rb +24 -0
- data/lib/rujira/api/user.rb +46 -0
- data/lib/rujira/client.rb +4 -4
- data/lib/rujira/request.rb +2 -0
- data/lib/rujira/resource/common.rb +10 -2
- data/lib/rujira/resource/issue.rb +4 -0
- data/lib/rujira/resource/issue_type.rb +27 -0
- data/lib/rujira/resource/myself.rb +12 -0
- data/lib/rujira/resource/priority.rb +27 -0
- data/lib/rujira/resource/project.rb +13 -0
- data/lib/rujira/resource/user.rb +61 -0
- data/lib/rujira/tasks/generate.rake +17 -62
- data/lib/rujira/tasks/issue.rb +83 -0
- data/lib/rujira/tasks/utils.rb +43 -0
- data/lib/rujira/version.rb +1 -1
- data/lib/rujira.rb +6 -0
- metadata +9 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 22f2c365275fa72514c36702efe3fda2463bdc1948dcc020f38148b4a25bac3a
|
|
4
|
+
data.tar.gz: 1a4995399b9f0ff4616fbef8627c3c3b717d5e0edcc9d3f1e1defb11d9262fe8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ecde3caf684b3907b6764a858ca723c09e19606fc91fa238c92c8648ba0b8827b08e7bbabbe39d221fcb6674517c9791315f88bd246145a4f02632f179deadab
|
|
7
|
+
data.tar.gz: a7abd29b1bdd8222ab99bf02432b4ba7fb396b8e5b3e4148bda3bd27fe70cce28f03bcef12aed0f7fb69a59bac9d6bfb4c4b7031764fb9b44359bddcd0cbadcb
|
data/CHANGELOG.md
CHANGED
|
@@ -1,11 +1,43 @@
|
|
|
1
|
-
## [0.7.
|
|
1
|
+
## [0.7.3] - 2026-03-27
|
|
2
2
|
|
|
3
3
|
### 🚀 Features
|
|
4
4
|
|
|
5
|
+
- Added priority API
|
|
6
|
+
- Added issue_type API and link generator
|
|
7
|
+
|
|
8
|
+
### 🚜 Refactor
|
|
9
|
+
|
|
10
|
+
- Create utils libs
|
|
11
|
+
- Added list of issue types
|
|
12
|
+
- Rename dispatchable to wrap_responses
|
|
13
|
+
- Use editor for enter description
|
|
14
|
+
- Added alias for payload
|
|
15
|
+
|
|
16
|
+
### 📚 Documentation
|
|
17
|
+
|
|
18
|
+
- Added short description for link generator
|
|
19
|
+
- Added example test for parallel usage
|
|
20
|
+
## [0.7.2] - 2026-03-26
|
|
21
|
+
|
|
22
|
+
### 🚀 Features
|
|
23
|
+
|
|
24
|
+
- Added user creation
|
|
25
|
+
## [0.7.1] - 2026-03-25
|
|
26
|
+
|
|
27
|
+
### 🚀 Features
|
|
28
|
+
|
|
29
|
+
- Use patch changes log
|
|
30
|
+
- Added exception raising for obj
|
|
31
|
+
- Added attach file alias
|
|
32
|
+
- Added api for task creation
|
|
5
33
|
- Added project as obj
|
|
6
34
|
|
|
7
35
|
### 🚜 Refactor
|
|
8
36
|
|
|
37
|
+
- Rename commitable to lazy
|
|
38
|
+
- Linter issues
|
|
39
|
+
- Added new methods for agile boards
|
|
40
|
+
- Added new task
|
|
9
41
|
- Tuning for tests
|
|
10
42
|
|
|
11
43
|
### 📚 Documentation
|
|
@@ -38,51 +70,3 @@
|
|
|
38
70
|
|
|
39
71
|
- Dispatchable for client
|
|
40
72
|
## [0.4.0] - 2025-09-13
|
|
41
|
-
|
|
42
|
-
### 🚀 Features
|
|
43
|
-
|
|
44
|
-
- Extend Issue #2
|
|
45
|
-
- Extend Issue
|
|
46
|
-
- Added Filter
|
|
47
|
-
- Extend Avatar, Configuration, CustomFields, Field
|
|
48
|
-
- Extend Attachments
|
|
49
|
-
- Added ApplicationRole
|
|
50
|
-
- Added ApplicationProperties
|
|
51
|
-
- Added permissions api
|
|
52
|
-
|
|
53
|
-
### 🐛 Bug Fixes
|
|
54
|
-
|
|
55
|
-
- Fix for tasks
|
|
56
|
-
|
|
57
|
-
### 🚜 Refactor
|
|
58
|
-
|
|
59
|
-
- Dont raising for faraday
|
|
60
|
-
- Cleanup attachments
|
|
61
|
-
- Split issue #3
|
|
62
|
-
- Split issue #2
|
|
63
|
-
- Split issue
|
|
64
|
-
## [0.3.3] - 2025-09-13
|
|
65
|
-
|
|
66
|
-
### 📚 Documentation
|
|
67
|
-
|
|
68
|
-
- Added comments from ai #4
|
|
69
|
-
- Added comments from ai #3
|
|
70
|
-
- Added comments from ai #2
|
|
71
|
-
- Added comments from ai
|
|
72
|
-
## [0.3.2] - 2025-09-13
|
|
73
|
-
|
|
74
|
-
### 🚜 Refactor
|
|
75
|
-
|
|
76
|
-
- Remove configuration
|
|
77
|
-
|
|
78
|
-
### 📚 Documentation
|
|
79
|
-
|
|
80
|
-
- Updated inline description
|
|
81
|
-
## [0.3.1] - 2025-09-13
|
|
82
|
-
|
|
83
|
-
### 🚜 Refactor
|
|
84
|
-
|
|
85
|
-
- Fix for headers setter
|
|
86
|
-
- Cleanup data method
|
|
87
|
-
- Abort if id is nil #2
|
|
88
|
-
- Abort if id is nil
|
data/README.md
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
# RUJIRA
|
|
2
2
|
|
|
3
|
+
[](https://github.com/itmagelab/rujira/actions/workflows/ruby.yml)
|
|
4
|
+
|
|
3
5
|
**RUJIRA** is a Ruby gem for easy interaction with the Jira API. It provides a simple and flexible interface to work with Jira resources and includes Rake tasks for convenient command-line operations.
|
|
4
6
|
|
|
7
|
+
This project was created as an alternative to <https://github.com/sumoheavy/jira-ruby>, offering a more user-friendly and intuitive interface. It lets you work with requests as objects or hash arrays, provides flexibility in choosing a connection adapter, and makes the codebase easier to maintain.
|
|
8
|
+
|
|
5
9
|
---
|
|
6
10
|
|
|
7
11
|
## Features
|
|
@@ -16,7 +20,7 @@
|
|
|
16
20
|
Add to your `Gemfile`:
|
|
17
21
|
|
|
18
22
|
```ruby
|
|
19
|
-
gem 'rujira', '~> 0.
|
|
23
|
+
gem 'rujira', '~> 0.7.0'
|
|
20
24
|
```
|
|
21
25
|
|
|
22
26
|
Or install directly:
|
|
@@ -40,6 +44,102 @@ LOG_LEVEL=error
|
|
|
40
44
|
|
|
41
45
|
### Example of usage
|
|
42
46
|
|
|
47
|
+
By default, we can use an object-oriented approach, but this method does not cover all API capabilities.
|
|
48
|
+
|
|
49
|
+
```ruby
|
|
50
|
+
url = ENV.fetch('RUJIRA_URL', 'http://localhost:8080')
|
|
51
|
+
client = Rujira::Client.new(url, wrap_responses: true)
|
|
52
|
+
|
|
53
|
+
project = random_name
|
|
54
|
+
me = client.Myself.get
|
|
55
|
+
project = me.create_software_project key: project.to_s,
|
|
56
|
+
name: project.to_s
|
|
57
|
+
task = project.add_task summary: 'BOT: added a new task.',
|
|
58
|
+
description: 'This task was generated by the bot when creating changes in the repository.'
|
|
59
|
+
task.add_comment 'Bot added a comment as obj #1'
|
|
60
|
+
task.attach_file '/tmp/upload.file'
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Demonstrates the full lifecycle of a Jira user: creation, retrieval, update, deactivation, and deletion using the Rujira client.
|
|
64
|
+
|
|
65
|
+
```ruby
|
|
66
|
+
url = ENV.fetch('RUJIRA_URL', 'http://localhost:8080')
|
|
67
|
+
client = Rujira::Client.new(url, wrap_responses: true)
|
|
68
|
+
|
|
69
|
+
username = random_name
|
|
70
|
+
me = client.Myself.get
|
|
71
|
+
|
|
72
|
+
user = client.User.create do
|
|
73
|
+
payload({
|
|
74
|
+
name: username,
|
|
75
|
+
password: username,
|
|
76
|
+
emailAddress: "#{username}@username",
|
|
77
|
+
displayName: "#{username} created be #{me.name}",
|
|
78
|
+
applicationKeys: ['jira-core']
|
|
79
|
+
})
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
user = client.User.get user.key
|
|
83
|
+
|
|
84
|
+
user.update do
|
|
85
|
+
payload emailAddress: 'root@test'
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
user.deactivate!
|
|
89
|
+
user.delete
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
This function demonstrates that the library supports executing requests in parallel using multiple threads. By processing tasks concurrently, it significantly improves performance when handling a large number of repetitive operations, such as creating or deleting entities.
|
|
93
|
+
|
|
94
|
+
```ruby
|
|
95
|
+
url = ENV.fetch('RUJIRA_URL', 'http://localhost:8080')
|
|
96
|
+
client = Rujira::Client.new(url, debug: true, wrap_responses: false, lazy: true)
|
|
97
|
+
|
|
98
|
+
me = client.Myself.get.execute
|
|
99
|
+
|
|
100
|
+
queue = Queue.new
|
|
101
|
+
|
|
102
|
+
project_name = random_name
|
|
103
|
+
project = client.Project.create do
|
|
104
|
+
payload key: project_name.to_s,
|
|
105
|
+
name: project_name.to_s,
|
|
106
|
+
projectTypeKey: 'software',
|
|
107
|
+
lead: me['name']
|
|
108
|
+
end.to_obj
|
|
109
|
+
|
|
110
|
+
count.times do
|
|
111
|
+
task = project.add_task summary: 'BOT: added a new task.',
|
|
112
|
+
description: 'This task was generated by the bot when creating changes in the repository.'
|
|
113
|
+
queue << task
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
workers = thread.times.map do
|
|
117
|
+
Thread.new do
|
|
118
|
+
until queue.empty?
|
|
119
|
+
begin
|
|
120
|
+
task = begin
|
|
121
|
+
queue.pop(true)
|
|
122
|
+
rescue StandardError
|
|
123
|
+
nil
|
|
124
|
+
end
|
|
125
|
+
next unless task
|
|
126
|
+
|
|
127
|
+
task = task.to_obj
|
|
128
|
+
|
|
129
|
+
task.delete
|
|
130
|
+
rescue StandardError => e
|
|
131
|
+
warn "Error in thread: #{e.message}"
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
workers.each(&:join)
|
|
138
|
+
project.delete
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Alternatively, we can work with the API directly, as with a regular request dispatcher; in this form, most operations are available.
|
|
142
|
+
|
|
43
143
|
```ruby
|
|
44
144
|
require 'date'
|
|
45
145
|
|
|
@@ -151,7 +251,9 @@ rake jira:dashboard:list # Get list of dashboards
|
|
|
151
251
|
rake jira:issue:attach # Example usage attaching in issue
|
|
152
252
|
rake jira:issue:create # Create a issue
|
|
153
253
|
rake jira:issue:delete # Delete issue
|
|
254
|
+
rake jira:issue:generate_link # Generate a Jira link for creating a new issue
|
|
154
255
|
rake jira:issue:search # Search issue by fields
|
|
256
|
+
rake jira:project:create # Create project
|
|
155
257
|
rake jira:project:list # Get list of projects
|
|
156
258
|
rake jira:server_info # Test connection by getting server information
|
|
157
259
|
rake jira:sprint:properties:list # Get sprint properties
|
|
@@ -165,6 +267,34 @@ rake jira:issue:search JQL='project = ITMG'
|
|
|
165
267
|
rake jira:issue:attach FILE='upload.png' ISSUE_ID='ITMG-1'
|
|
166
268
|
```
|
|
167
269
|
|
|
270
|
+
### Generate a Jira Issue Creation Link
|
|
271
|
+
|
|
272
|
+
The `generate_link` task interactively collects input (project, summary, description, and issue type) and generates a ready-to-use Jira URL with pre-filled fields for creating a new issue.
|
|
273
|
+
|
|
274
|
+
It opens your default editor for entering the description and then outputs a link that can be opened in a browser.
|
|
275
|
+
|
|
276
|
+
#### Usage
|
|
277
|
+
|
|
278
|
+
```
|
|
279
|
+
rake jira::issue::generate_link
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
#### Example session
|
|
283
|
+
|
|
284
|
+
```
|
|
285
|
+
Project key (e.g., ABC): TEST
|
|
286
|
+
Summary (short description): Fix login bug
|
|
287
|
+
Opening editor for description...
|
|
288
|
+
Issue type (Bug/Task/Story): Bug
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
#### Output
|
|
292
|
+
|
|
293
|
+
```
|
|
294
|
+
Generated issue creation link:
|
|
295
|
+
https://your-jira-instance/secure/CreateIssueDetails!init.jspa?pid=10000&summary=Fix+login+bug&description=Steps+to+reproduce...&reporter=john.doe&issuetype=1
|
|
296
|
+
```
|
|
297
|
+
|
|
168
298
|
## Development runs
|
|
169
299
|
|
|
170
300
|
```bash
|
data/Rakefile
CHANGED
|
@@ -23,11 +23,3 @@ end
|
|
|
23
23
|
task :version do
|
|
24
24
|
puts Rujira::VERSION
|
|
25
25
|
end
|
|
26
|
-
|
|
27
|
-
desc 'Cleanup test installation'
|
|
28
|
-
task :cleanup do
|
|
29
|
-
url = ENV.fetch('RUJIRA_URL', 'http://localhost:8080')
|
|
30
|
-
client = Rujira::Client.new(url, dispatchable: false)
|
|
31
|
-
projects = client.Project.list
|
|
32
|
-
projects.map(&:delete)
|
|
33
|
-
end
|
data/cliff.toml
CHANGED
data/compose.yaml
CHANGED
data/lib/rujira/api/board.rb
CHANGED
|
@@ -8,7 +8,7 @@ module Rujira
|
|
|
8
8
|
# API reference:
|
|
9
9
|
# https://docs.atlassian.com/jira-software/REST/9.17.0/#agile/1.0/board
|
|
10
10
|
#
|
|
11
|
-
class Board < Common
|
|
11
|
+
class Board < Common # rubocop:disable Metrics/ClassLength
|
|
12
12
|
# Initializes a new Board API client.
|
|
13
13
|
#
|
|
14
14
|
# @param [Object] client The HTTP client instance used to perform requests.
|
|
@@ -63,6 +63,145 @@ module Rujira
|
|
|
63
63
|
call
|
|
64
64
|
end
|
|
65
65
|
|
|
66
|
+
def create(&block)
|
|
67
|
+
builder do
|
|
68
|
+
method :post
|
|
69
|
+
path 'board'
|
|
70
|
+
instance_eval(&block) if block_given?
|
|
71
|
+
end
|
|
72
|
+
call
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def delete(id, &block)
|
|
76
|
+
abort 'Board ID is required' if id.to_s.strip.empty?
|
|
77
|
+
builder do
|
|
78
|
+
method :delete
|
|
79
|
+
path "board/#{id}"
|
|
80
|
+
instance_eval(&block) if block_given?
|
|
81
|
+
end
|
|
82
|
+
call
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def backlog(id, &block)
|
|
86
|
+
abort 'Board ID is required' if id.to_s.strip.empty?
|
|
87
|
+
builder do
|
|
88
|
+
path "board/#{id}/backlog"
|
|
89
|
+
instance_eval(&block) if block_given?
|
|
90
|
+
end
|
|
91
|
+
call
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def configuration(id, &block)
|
|
95
|
+
abort 'Board ID is required' if id.to_s.strip.empty?
|
|
96
|
+
builder do
|
|
97
|
+
path "board/#{id}/configuration"
|
|
98
|
+
instance_eval(&block) if block_given?
|
|
99
|
+
end
|
|
100
|
+
call
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def issue(id, &block)
|
|
104
|
+
abort 'Board ID is required' if id.to_s.strip.empty?
|
|
105
|
+
builder do
|
|
106
|
+
path "board/#{id}/issue"
|
|
107
|
+
instance_eval(&block) if block_given?
|
|
108
|
+
end
|
|
109
|
+
call
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def epic(id, &block)
|
|
113
|
+
abort 'Board ID is required' if id.to_s.strip.empty?
|
|
114
|
+
builder do
|
|
115
|
+
path "board/#{id}/epic"
|
|
116
|
+
instance_eval(&block) if block_given?
|
|
117
|
+
end
|
|
118
|
+
call
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def epic_issues(id, epic_id, &block)
|
|
122
|
+
abort 'Board ID is required' if id.to_s.strip.empty?
|
|
123
|
+
builder do
|
|
124
|
+
path "board/#{id}/epic/#{epic_id}/issue"
|
|
125
|
+
instance_eval(&block) if block_given?
|
|
126
|
+
end
|
|
127
|
+
call
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def epic_none_issues(id, &block)
|
|
131
|
+
abort 'Board ID is required' if id.to_s.strip.empty?
|
|
132
|
+
builder do
|
|
133
|
+
path "board/#{id}/epic/none/issue"
|
|
134
|
+
instance_eval(&block) if block_given?
|
|
135
|
+
end
|
|
136
|
+
call
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def project(id, &block)
|
|
140
|
+
abort 'Board ID is required' if id.to_s.strip.empty?
|
|
141
|
+
builder do
|
|
142
|
+
path "board/#{id}/project"
|
|
143
|
+
instance_eval(&block) if block_given?
|
|
144
|
+
end
|
|
145
|
+
call
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def settings(id, &block)
|
|
149
|
+
abort 'Board ID is required' if id.to_s.strip.empty?
|
|
150
|
+
builder do
|
|
151
|
+
path "board/#{id}/settings/refined-velocity"
|
|
152
|
+
instance_eval(&block) if block_given?
|
|
153
|
+
end
|
|
154
|
+
call
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def set_settings(id, &block)
|
|
158
|
+
abort 'Board ID is required' if id.to_s.strip.empty?
|
|
159
|
+
builder do
|
|
160
|
+
method :put
|
|
161
|
+
path "board/#{id}/settings/refined-velocity"
|
|
162
|
+
instance_eval(&block) if block_given?
|
|
163
|
+
end
|
|
164
|
+
call
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def properties(id, &block)
|
|
168
|
+
abort 'Board ID is required' if id.to_s.strip.empty?
|
|
169
|
+
builder do
|
|
170
|
+
path "board/#{id}/properties"
|
|
171
|
+
instance_eval(&block) if block_given?
|
|
172
|
+
end
|
|
173
|
+
call
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def set_properties(id, property_key, &block)
|
|
177
|
+
abort 'board id is required' if id.to_s.strip.empty?
|
|
178
|
+
builder do
|
|
179
|
+
method :put
|
|
180
|
+
path "board/#{id}/properties/#{property_key}"
|
|
181
|
+
instance_eval(&block) if block_given?
|
|
182
|
+
end
|
|
183
|
+
call
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def get_properties(id, property_key, &block)
|
|
187
|
+
abort 'board id is required' if id.to_s.strip.empty?
|
|
188
|
+
builder do
|
|
189
|
+
path "board/#{id}/properties/#{property_key}"
|
|
190
|
+
instance_eval(&block) if block_given?
|
|
191
|
+
end
|
|
192
|
+
call
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def delete_properties(id, property_key, &block)
|
|
196
|
+
abort 'board id is required' if id.to_s.strip.empty?
|
|
197
|
+
builder do
|
|
198
|
+
method :delete
|
|
199
|
+
path "board/#{id}/properties/#{property_key}"
|
|
200
|
+
instance_eval(&block) if block_given?
|
|
201
|
+
end
|
|
202
|
+
call
|
|
203
|
+
end
|
|
204
|
+
|
|
66
205
|
# Retrieves all sprints for a specific board.
|
|
67
206
|
#
|
|
68
207
|
# Available query parameters:
|
data/lib/rujira/api/common.rb
CHANGED
|
@@ -40,8 +40,8 @@ module Rujira
|
|
|
40
40
|
# @return [Object] The API response after dispatching the request.
|
|
41
41
|
def call
|
|
42
42
|
@client.logger.debug "Call the method: #{caller_locations(1, 1)[0].label}"
|
|
43
|
-
return @client.dispatch(@request)
|
|
44
|
-
return self if @client.
|
|
43
|
+
return @client.dispatch(@request) unless @client.wrap_responses
|
|
44
|
+
return self if @client.lazy
|
|
45
45
|
|
|
46
46
|
to_obj
|
|
47
47
|
end
|
|
@@ -52,6 +52,7 @@ module Rujira
|
|
|
52
52
|
def commit
|
|
53
53
|
@client.dispatch(@request)
|
|
54
54
|
end
|
|
55
|
+
alias execute commit
|
|
55
56
|
|
|
56
57
|
# Converts the API response into structured Ruby objects.
|
|
57
58
|
# If the response is an array of hashes, maps each element through `process`.
|
|
@@ -59,9 +60,9 @@ module Rujira
|
|
|
59
60
|
#
|
|
60
61
|
# @return [Object] Processed response as one or more resource objects, or original response.
|
|
61
62
|
def to_obj
|
|
62
|
-
response =
|
|
63
|
+
response = execute
|
|
63
64
|
|
|
64
|
-
return response.map { |el| process(el) } if response.is_a?(Array) && response.all?
|
|
65
|
+
return response.map { |el| process(el) } if response.is_a?(Array) && response.all?(Hash)
|
|
65
66
|
return response unless response.is_a?(Hash)
|
|
66
67
|
|
|
67
68
|
process response
|
|
@@ -76,7 +77,12 @@ module Rujira
|
|
|
76
77
|
def process(response)
|
|
77
78
|
response.merge!(@metadata)
|
|
78
79
|
resource_class_name = self.class.name.sub('Api', 'Resource')
|
|
79
|
-
|
|
80
|
+
begin
|
|
81
|
+
Object.const_get(resource_class_name).new(@client, **response)
|
|
82
|
+
rescue NameError
|
|
83
|
+
raise "Resource class '#{resource_class_name}' not found. " \
|
|
84
|
+
'Please ensure the class exists or use wrap_responses mode.'
|
|
85
|
+
end
|
|
80
86
|
end
|
|
81
87
|
|
|
82
88
|
# Sets ownership context for the resource by storing a parent ID or key
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Rujira
|
|
4
|
+
module Api
|
|
5
|
+
# API reference:
|
|
6
|
+
# https://docs.atlassian.com/software/jira/docs/api/REST/9.17.0/#api/2/issuetype
|
|
7
|
+
#
|
|
8
|
+
class IssueType < Common
|
|
9
|
+
def get(&block)
|
|
10
|
+
builder do
|
|
11
|
+
path 'issuetype'
|
|
12
|
+
method :get
|
|
13
|
+
instance_eval(&block) if block_given?
|
|
14
|
+
end
|
|
15
|
+
call
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def get_by_name(name, &block)
|
|
19
|
+
issue_types = get(&block)
|
|
20
|
+
issue_types.find { |type| type.name == name }
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Rujira
|
|
4
|
+
module Api
|
|
5
|
+
# API reference:
|
|
6
|
+
# https://docs.atlassian.com/software/jira/docs/api/REST/9.17.0/#api/2/priority
|
|
7
|
+
#
|
|
8
|
+
class Priority < Common
|
|
9
|
+
def get(&block)
|
|
10
|
+
builder do
|
|
11
|
+
path 'priority'
|
|
12
|
+
method :get
|
|
13
|
+
instance_eval(&block) if block_given?
|
|
14
|
+
end
|
|
15
|
+
call
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def get_by_name(name, &block)
|
|
19
|
+
priorities = get(&block)
|
|
20
|
+
priorities.find { |type| type.name == name }
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Rujira
|
|
4
|
+
module Api
|
|
5
|
+
class User < Common # rubocop:disable Style/Documentation
|
|
6
|
+
def create(&block)
|
|
7
|
+
builder do
|
|
8
|
+
path 'user'
|
|
9
|
+
method :post
|
|
10
|
+
instance_eval(&block) if block_given?
|
|
11
|
+
end
|
|
12
|
+
call
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def update(key, &block)
|
|
16
|
+
builder do
|
|
17
|
+
path 'user'
|
|
18
|
+
method :put
|
|
19
|
+
params key: key
|
|
20
|
+
instance_eval(&block) if block_given?
|
|
21
|
+
end
|
|
22
|
+
call
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def get(key = nil, include_deleted: false, &block)
|
|
26
|
+
builder do
|
|
27
|
+
path 'user'
|
|
28
|
+
method :get
|
|
29
|
+
params key: key, includeDeleted: include_deleted
|
|
30
|
+
instance_eval(&block) if block_given?
|
|
31
|
+
end
|
|
32
|
+
call
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def delete(key, &block)
|
|
36
|
+
builder do
|
|
37
|
+
path 'user'
|
|
38
|
+
method :delete
|
|
39
|
+
params key: key
|
|
40
|
+
instance_eval(&block) if block_given?
|
|
41
|
+
end
|
|
42
|
+
call
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
data/lib/rujira/client.rb
CHANGED
|
@@ -11,7 +11,7 @@ module Rujira
|
|
|
11
11
|
# client.issue.get("TEST-123")
|
|
12
12
|
#
|
|
13
13
|
class Client
|
|
14
|
-
attr_reader :
|
|
14
|
+
attr_reader :wrap_responses, :logger, :lazy
|
|
15
15
|
|
|
16
16
|
SUPPORTED_METHODS = %i[get delete head post put patch].freeze
|
|
17
17
|
|
|
@@ -23,9 +23,9 @@ module Rujira
|
|
|
23
23
|
# @example Initialize client
|
|
24
24
|
# client = Rujira::Client.new("https://jira.example.com", debug: true)
|
|
25
25
|
#
|
|
26
|
-
def initialize(url, debug: false,
|
|
27
|
-
@
|
|
28
|
-
@
|
|
26
|
+
def initialize(url, debug: false, wrap_responses: false, lazy: false, log_level: 'error') # rubocop:disable Metrics/MethodLength
|
|
27
|
+
@wrap_responses = wrap_responses
|
|
28
|
+
@lazy = lazy
|
|
29
29
|
@uri = URI(url)
|
|
30
30
|
@debug = ENV.fetch('RUJIRA_DEBUG', debug.to_s) == 'true'
|
|
31
31
|
@raise_error = false
|
data/lib/rujira/request.rb
CHANGED
|
@@ -2,9 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
module Rujira
|
|
4
4
|
module Resource
|
|
5
|
-
class Common
|
|
6
|
-
|
|
5
|
+
class Common # rubocop:disable Style/Documentation
|
|
6
|
+
attr_reader :response
|
|
7
|
+
|
|
8
|
+
def initialize(client, **response)
|
|
7
9
|
@client = client
|
|
10
|
+
@response = response
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def reload!
|
|
14
|
+
user = @client.User.get(@key)
|
|
15
|
+
initialize(@client, **user.response)
|
|
8
16
|
end
|
|
9
17
|
end
|
|
10
18
|
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Rujira
|
|
4
|
+
module Resource
|
|
5
|
+
# TODO
|
|
6
|
+
class IssueType < Common
|
|
7
|
+
# @return [String] The ID of the issue
|
|
8
|
+
attr_reader :id
|
|
9
|
+
# @return [String] The key of the issue (e.g., "TEST-123")
|
|
10
|
+
attr_reader :name
|
|
11
|
+
# @return [String] The URL to access this issue via Jira REST API
|
|
12
|
+
attr_reader :url
|
|
13
|
+
|
|
14
|
+
# Initializes an IssueType resource
|
|
15
|
+
#
|
|
16
|
+
# @param [Object] client The API client instance used to make requests
|
|
17
|
+
# @param [Hash] hash The issue data from the Jira API
|
|
18
|
+
def initialize(client, **args)
|
|
19
|
+
super
|
|
20
|
+
|
|
21
|
+
@id = args['id']
|
|
22
|
+
@name = args['name']
|
|
23
|
+
@url = args['self']
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -25,6 +25,18 @@ module Rujira
|
|
|
25
25
|
@name = args['name']
|
|
26
26
|
@email = args['emailAddress']
|
|
27
27
|
end
|
|
28
|
+
|
|
29
|
+
def create_software_project(**args)
|
|
30
|
+
key = args[:key]
|
|
31
|
+
project_name = args[:name]
|
|
32
|
+
name = @name
|
|
33
|
+
@client.Project.create do
|
|
34
|
+
payload key: key,
|
|
35
|
+
name: project_name,
|
|
36
|
+
projectTypeKey: 'software',
|
|
37
|
+
lead: name
|
|
38
|
+
end
|
|
39
|
+
end
|
|
28
40
|
end
|
|
29
41
|
end
|
|
30
42
|
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Rujira
|
|
4
|
+
module Resource
|
|
5
|
+
# TODO
|
|
6
|
+
class Priority < Common
|
|
7
|
+
# @return [String] The ID of the issue
|
|
8
|
+
attr_reader :id
|
|
9
|
+
# @return [String] The key of the issue (e.g., "TEST-123")
|
|
10
|
+
attr_reader :name
|
|
11
|
+
# @return [String] The URL to access this issue via Jira REST API
|
|
12
|
+
attr_reader :url
|
|
13
|
+
|
|
14
|
+
# Initializes an Priority resource
|
|
15
|
+
#
|
|
16
|
+
# @param [Object] client The API client instance used to make requests
|
|
17
|
+
# @param [Hash] hash The issue data from the Jira API
|
|
18
|
+
def initialize(client, **args)
|
|
19
|
+
super
|
|
20
|
+
|
|
21
|
+
@id = args['id']
|
|
22
|
+
@name = args['name']
|
|
23
|
+
@url = args['self']
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -30,6 +30,19 @@ module Rujira
|
|
|
30
30
|
def delete
|
|
31
31
|
@client.Project.delete(@id)
|
|
32
32
|
end
|
|
33
|
+
|
|
34
|
+
def add_task(**args)
|
|
35
|
+
key = @key
|
|
36
|
+
@client.Issue.create do
|
|
37
|
+
payload fields: {
|
|
38
|
+
project: { key: key },
|
|
39
|
+
summary: args[:summary],
|
|
40
|
+
description: args[:description],
|
|
41
|
+
issuetype: { name: 'Task' }
|
|
42
|
+
}
|
|
43
|
+
params updateHistory: true
|
|
44
|
+
end
|
|
45
|
+
end
|
|
33
46
|
end
|
|
34
47
|
end
|
|
35
48
|
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Rujira
|
|
4
|
+
module Resource
|
|
5
|
+
# Represents a Jira issue resource.
|
|
6
|
+
# Provides access to issue attributes and actions such as adding comments.
|
|
7
|
+
#
|
|
8
|
+
# Example usage:
|
|
9
|
+
# issue = Rujira::Resource::User.new(client, data)
|
|
10
|
+
# issue.add_comment("This is a comment")
|
|
11
|
+
#
|
|
12
|
+
class User < Common
|
|
13
|
+
# @return [String] The URL to access this issue via Jira REST API
|
|
14
|
+
attr_reader :url
|
|
15
|
+
# @return [String] The key of the issue (e.g., "TEST-123")
|
|
16
|
+
attr_reader :key
|
|
17
|
+
attr_reader :name, :email, :display_name, :active
|
|
18
|
+
|
|
19
|
+
# Initializes an User resource
|
|
20
|
+
#
|
|
21
|
+
# @param [Object] client The API client instance used to make requests
|
|
22
|
+
# @param [Hash] hash The issue data from the Jira API
|
|
23
|
+
def initialize(client, **args)
|
|
24
|
+
super
|
|
25
|
+
|
|
26
|
+
@url = args['self']
|
|
27
|
+
@key = args['key']
|
|
28
|
+
@name = args['name']
|
|
29
|
+
@email = args['emailAddress']
|
|
30
|
+
@display_name = args['displayName']
|
|
31
|
+
@active = args.fetch('active', true)
|
|
32
|
+
@deleted = args.fetch('deleted', false)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def delete
|
|
36
|
+
@client.User.delete(@key)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def update(&block)
|
|
40
|
+
@client.User.update(@key) do
|
|
41
|
+
instance_eval(&block) if block_given?
|
|
42
|
+
end
|
|
43
|
+
reload!
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def deactivate!
|
|
47
|
+
@client.User.update(@key) do
|
|
48
|
+
payload active: false
|
|
49
|
+
end
|
|
50
|
+
reload!
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def activate!
|
|
54
|
+
@client.User.update(@key) do
|
|
55
|
+
payload active: true
|
|
56
|
+
end
|
|
57
|
+
reload!
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -10,31 +10,16 @@ module Rujira
|
|
|
10
10
|
# TODO
|
|
11
11
|
class Jira
|
|
12
12
|
include Rake::DSL if defined?(Rake::DSL)
|
|
13
|
+
require_relative 'utils'
|
|
14
|
+
|
|
13
15
|
def initialize
|
|
14
16
|
generate
|
|
15
17
|
end
|
|
16
18
|
|
|
17
|
-
def client
|
|
18
|
-
url = ENV.fetch('RUJIRA_URL', 'http://localhost:8080')
|
|
19
|
-
@client ||= Rujira::Client.new(url, debug: false)
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def fetch_options(params, name)
|
|
23
|
-
help = params.map { |k| "#{k}=<VALUE>" }.join(' ')
|
|
24
|
-
options = params.to_h do |k|
|
|
25
|
-
[k.downcase.to_sym, ENV.fetch(k, nil)]
|
|
26
|
-
end
|
|
27
|
-
missing = options.select { |_, v| v.nil? }.keys
|
|
28
|
-
unless missing.empty?
|
|
29
|
-
abort "❌ ERROR: The following required environment variables are missing: #{missing.join(', ').upcase}\n" \
|
|
30
|
-
"✅ USAGE: rake #{name} #{help}"
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
options
|
|
34
|
-
end
|
|
35
|
-
|
|
36
19
|
def generate # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
|
|
37
|
-
namespace :jira do
|
|
20
|
+
namespace :jira do # rubocop:disable Metrics/BlockLength
|
|
21
|
+
require_relative 'issue'
|
|
22
|
+
|
|
38
23
|
desc 'Test connection by getting username'
|
|
39
24
|
task :whoami do
|
|
40
25
|
result = client.Myself.get
|
|
@@ -53,6 +38,18 @@ module Rujira
|
|
|
53
38
|
result = client.Project.list
|
|
54
39
|
puts JSON.pretty_generate(result)
|
|
55
40
|
end
|
|
41
|
+
|
|
42
|
+
desc 'Create project'
|
|
43
|
+
task :create do |t|
|
|
44
|
+
options = fetch_options(%w[KEY NAME TYPE LEAD], t.name)
|
|
45
|
+
result = client.Project.create do
|
|
46
|
+
payload key: options[:key],
|
|
47
|
+
name: options[:name],
|
|
48
|
+
projectTypeKey: options[:type],
|
|
49
|
+
lead: options[:lead]
|
|
50
|
+
end
|
|
51
|
+
puts JSON.pretty_generate(result)
|
|
52
|
+
end
|
|
56
53
|
end
|
|
57
54
|
|
|
58
55
|
namespace :dashboard do
|
|
@@ -106,48 +103,6 @@ module Rujira
|
|
|
106
103
|
end
|
|
107
104
|
end
|
|
108
105
|
end
|
|
109
|
-
|
|
110
|
-
namespace :issue do
|
|
111
|
-
desc 'Create a issue'
|
|
112
|
-
task :create do |t|
|
|
113
|
-
options = fetch_options(%w[PROJECT SUMMARY DESCRIPTION ISSUETYPE], t.name)
|
|
114
|
-
abort 'ISSUETYPE must start with a capital letter' unless options[:issuetype].match?(/\A[A-Z]/)
|
|
115
|
-
|
|
116
|
-
result = client.Issue.create do
|
|
117
|
-
payload fields: {
|
|
118
|
-
project: { key: options[:project] },
|
|
119
|
-
summary: options[:summary],
|
|
120
|
-
issuetype: { name: options[:issuetype] },
|
|
121
|
-
description: options[:description]
|
|
122
|
-
}
|
|
123
|
-
end
|
|
124
|
-
puts JSON.pretty_generate(result)
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
desc 'Search issue by fields'
|
|
128
|
-
task :search do |t|
|
|
129
|
-
options = fetch_options(%w[JQL], t.name)
|
|
130
|
-
result = client.Search.get do
|
|
131
|
-
data jql: options[:jql]
|
|
132
|
-
end
|
|
133
|
-
result['issues'].each { |i| puts JSON.pretty_generate(i) }
|
|
134
|
-
end
|
|
135
|
-
|
|
136
|
-
desc 'Delete issue'
|
|
137
|
-
task :delete do |t|
|
|
138
|
-
options = fetch_options(%w[ISSUE_ID], t.name)
|
|
139
|
-
|
|
140
|
-
client.Issue.del options[:issue_id]
|
|
141
|
-
end
|
|
142
|
-
|
|
143
|
-
desc 'Example usage attaching in issue'
|
|
144
|
-
task :attach do |t|
|
|
145
|
-
options = fetch_options(%w[FILE ISSUE_ID], t.name)
|
|
146
|
-
|
|
147
|
-
result = client.Issue.attachments options[:issue_id], @options[:file]
|
|
148
|
-
puts JSON.pretty_generate(result)
|
|
149
|
-
end
|
|
150
|
-
end
|
|
151
106
|
end
|
|
152
107
|
end
|
|
153
108
|
end
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
namespace :issue do # rubocop:disable Metrics/BlockLength
|
|
4
|
+
desc 'Create a issue'
|
|
5
|
+
task :create do |t|
|
|
6
|
+
options = fetch_options(%w[PROJECT_KEY SUMMARY DESCRIPTION ISSUETYPE], t.name)
|
|
7
|
+
abort 'ISSUETYPE must start with a capital letter' unless options[:issuetype].match?(/\A[A-Z]/)
|
|
8
|
+
|
|
9
|
+
result = client.Issue.create do
|
|
10
|
+
payload fields: {
|
|
11
|
+
project: { key: options[:project_key] },
|
|
12
|
+
summary: options[:summary],
|
|
13
|
+
issuetype: { name: options[:issuetype] },
|
|
14
|
+
description: options[:description]
|
|
15
|
+
}
|
|
16
|
+
end
|
|
17
|
+
puts JSON.pretty_generate(result)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
desc 'Generate a Jira link for creating a new issue'
|
|
21
|
+
task :generate_link do # rubocop:disable Metrics/BlockLength
|
|
22
|
+
require 'cgi'
|
|
23
|
+
|
|
24
|
+
me = client_wrapped.Myself.get
|
|
25
|
+
server_info = client.ServerInfo.get
|
|
26
|
+
base_url = server_info['baseUrl']
|
|
27
|
+
|
|
28
|
+
print 'Project key (e.g., ABC): '
|
|
29
|
+
project_key = $stdin.gets.chomp
|
|
30
|
+
project = client_wrapped.Project.get(project_key)
|
|
31
|
+
|
|
32
|
+
print 'Summary (short description): '
|
|
33
|
+
summary = $stdin.gets.chomp
|
|
34
|
+
|
|
35
|
+
puts 'Opening editor for description...'
|
|
36
|
+
description = open_editor
|
|
37
|
+
|
|
38
|
+
issue_types = client_wrapped.IssueType.get
|
|
39
|
+
names = issue_types.map(&:name).join('/')
|
|
40
|
+
print "Issue type (#{names}): "
|
|
41
|
+
issue_type_name = $stdin.gets.chomp
|
|
42
|
+
issue_type = issue_types.find do |i|
|
|
43
|
+
i.name.downcase == issue_type_name.downcase
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
encoded_summary = CGI.escape(summary)
|
|
47
|
+
encoded_description = CGI.escape(description)
|
|
48
|
+
|
|
49
|
+
jira_url = "#{base_url}/secure/CreateIssueDetails!init.jspa" \
|
|
50
|
+
"?pid=#{project.id}" \
|
|
51
|
+
"&summary=#{encoded_summary}" \
|
|
52
|
+
"&description=#{encoded_description}" \
|
|
53
|
+
"&reporter=#{me.name}" \
|
|
54
|
+
"&issuetype=#{issue_type.id}"
|
|
55
|
+
|
|
56
|
+
puts "\nGenerated issue creation link:"
|
|
57
|
+
puts jira_url
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
desc 'Search issue by fields'
|
|
61
|
+
task :search do |t|
|
|
62
|
+
options = fetch_options(%w[JQL], t.name)
|
|
63
|
+
result = client.Search.get do
|
|
64
|
+
data jql: options[:jql]
|
|
65
|
+
end
|
|
66
|
+
result['issues'].each { |i| puts JSON.pretty_generate(i) }
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
desc 'Delete issue'
|
|
70
|
+
task :delete do |t|
|
|
71
|
+
options = fetch_options(%w[ISSUE_ID], t.name)
|
|
72
|
+
|
|
73
|
+
client.Issue.del options[:issue_id]
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
desc 'Example usage attaching in issue'
|
|
77
|
+
task :attach do |t|
|
|
78
|
+
options = fetch_options(%w[FILE ISSUE_ID], t.name)
|
|
79
|
+
|
|
80
|
+
result = client.Issue.attachments options[:issue_id], @options[:file]
|
|
81
|
+
puts JSON.pretty_generate(result)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
def client
|
|
4
|
+
url = ENV.fetch('RUJIRA_URL', 'http://localhost:8080')
|
|
5
|
+
@client ||= Rujira::Client.new(url, debug: false)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def client_wrapped
|
|
9
|
+
url = ENV.fetch('RUJIRA_URL', 'http://localhost:8080')
|
|
10
|
+
@client_wrapped ||= Rujira::Client.new(url, debug: false, wrap_responses: true)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def open_editor(initial_text = '')
|
|
14
|
+
require 'tempfile'
|
|
15
|
+
|
|
16
|
+
editor = ENV['EDITOR'] || 'vi'
|
|
17
|
+
|
|
18
|
+
file = Tempfile.new(['jira_description', '.txt'])
|
|
19
|
+
file.write(initial_text)
|
|
20
|
+
file.flush
|
|
21
|
+
file.close
|
|
22
|
+
|
|
23
|
+
system("#{editor} #{file.path}")
|
|
24
|
+
|
|
25
|
+
content = File.read(file.path)
|
|
26
|
+
file.unlink
|
|
27
|
+
|
|
28
|
+
content
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def fetch_options(params, name)
|
|
32
|
+
help = params.map { |k| "#{k}=<VALUE>" }.join(' ')
|
|
33
|
+
options = params.to_h do |k|
|
|
34
|
+
[k.downcase.to_sym, ENV.fetch(k, nil)]
|
|
35
|
+
end
|
|
36
|
+
missing = options.select { |_, v| v.nil? }.keys
|
|
37
|
+
unless missing.empty?
|
|
38
|
+
abort "❌ ERROR: The following required environment variables are missing: #{missing.join(', ').upcase}\n" \
|
|
39
|
+
"✅ USAGE: rake #{name} #{help}"
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
options
|
|
43
|
+
end
|
data/lib/rujira/version.rb
CHANGED
data/lib/rujira.rb
CHANGED
|
@@ -34,6 +34,12 @@ require_relative 'rujira/api/configuration'
|
|
|
34
34
|
require_relative 'rujira/api/custom_fields'
|
|
35
35
|
require_relative 'rujira/api/field'
|
|
36
36
|
require_relative 'rujira/api/filter'
|
|
37
|
+
require_relative 'rujira/api/user'
|
|
38
|
+
require_relative 'rujira/resource/user'
|
|
39
|
+
require_relative 'rujira/api/issue_type'
|
|
40
|
+
require_relative 'rujira/resource/issue_type'
|
|
41
|
+
require_relative 'rujira/api/priority'
|
|
42
|
+
require_relative 'rujira/resource/priority'
|
|
37
43
|
|
|
38
44
|
# Main Rujira module.
|
|
39
45
|
# 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.7.
|
|
4
|
+
version: 0.7.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Andrey Semenov
|
|
@@ -71,20 +71,28 @@ files:
|
|
|
71
71
|
- lib/rujira/api/issue.rb
|
|
72
72
|
- lib/rujira/api/issue/comments.rb
|
|
73
73
|
- lib/rujira/api/issue/watchers.rb
|
|
74
|
+
- lib/rujira/api/issue_type.rb
|
|
74
75
|
- lib/rujira/api/myself.rb
|
|
75
76
|
- lib/rujira/api/permissions.rb
|
|
77
|
+
- lib/rujira/api/priority.rb
|
|
76
78
|
- lib/rujira/api/project.rb
|
|
77
79
|
- lib/rujira/api/search.rb
|
|
78
80
|
- lib/rujira/api/server_info.rb
|
|
79
81
|
- lib/rujira/api/sprint.rb
|
|
82
|
+
- lib/rujira/api/user.rb
|
|
80
83
|
- lib/rujira/client.rb
|
|
81
84
|
- lib/rujira/request.rb
|
|
82
85
|
- lib/rujira/resource/comment.rb
|
|
83
86
|
- lib/rujira/resource/common.rb
|
|
84
87
|
- lib/rujira/resource/issue.rb
|
|
88
|
+
- lib/rujira/resource/issue_type.rb
|
|
85
89
|
- lib/rujira/resource/myself.rb
|
|
90
|
+
- lib/rujira/resource/priority.rb
|
|
86
91
|
- lib/rujira/resource/project.rb
|
|
92
|
+
- lib/rujira/resource/user.rb
|
|
87
93
|
- lib/rujira/tasks/generate.rake
|
|
94
|
+
- lib/rujira/tasks/issue.rb
|
|
95
|
+
- lib/rujira/tasks/utils.rb
|
|
88
96
|
- lib/rujira/version.rb
|
|
89
97
|
- sig/rujira.rbs
|
|
90
98
|
homepage: https://github.com/itmagelabs/rujira
|