rujira 0.7.1 → 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 +109 -1
- data/Rakefile +0 -8
- data/cliff.toml +3 -0
- data/examples/create_issue_as_obj.rb +1 -1
- data/examples/create_issue_in_sprint.rb +1 -1
- data/lib/rujira/api/common.rb +2 -2
- 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 +3 -3
- data/lib/rujira/request.rb +2 -0
- data/lib/rujira/resource/common.rb +9 -1
- data/lib/rujira/resource/issue_type.rb +27 -0
- data/lib/rujira/resource/priority.rb +27 -0
- data/lib/rujira/resource/user.rb +61 -0
- data/lib/rujira/tasks/generate.rake +5 -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
|
@@ -48,7 +48,7 @@ By default, we can use an object-oriented approach, but this method does not cov
|
|
|
48
48
|
|
|
49
49
|
```ruby
|
|
50
50
|
url = ENV.fetch('RUJIRA_URL', 'http://localhost:8080')
|
|
51
|
-
client = Rujira::Client.new(url,
|
|
51
|
+
client = Rujira::Client.new(url, wrap_responses: true)
|
|
52
52
|
|
|
53
53
|
project = random_name
|
|
54
54
|
me = client.Myself.get
|
|
@@ -60,6 +60,84 @@ task.add_comment 'Bot added a comment as obj #1'
|
|
|
60
60
|
task.attach_file '/tmp/upload.file'
|
|
61
61
|
```
|
|
62
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
|
+
|
|
63
141
|
Alternatively, we can work with the API directly, as with a regular request dispatcher; in this form, most operations are available.
|
|
64
142
|
|
|
65
143
|
```ruby
|
|
@@ -173,7 +251,9 @@ rake jira:dashboard:list # Get list of dashboards
|
|
|
173
251
|
rake jira:issue:attach # Example usage attaching in issue
|
|
174
252
|
rake jira:issue:create # Create a issue
|
|
175
253
|
rake jira:issue:delete # Delete issue
|
|
254
|
+
rake jira:issue:generate_link # Generate a Jira link for creating a new issue
|
|
176
255
|
rake jira:issue:search # Search issue by fields
|
|
256
|
+
rake jira:project:create # Create project
|
|
177
257
|
rake jira:project:list # Get list of projects
|
|
178
258
|
rake jira:server_info # Test connection by getting server information
|
|
179
259
|
rake jira:sprint:properties:list # Get sprint properties
|
|
@@ -187,6 +267,34 @@ rake jira:issue:search JQL='project = ITMG'
|
|
|
187
267
|
rake jira:issue:attach FILE='upload.png' ISSUE_ID='ITMG-1'
|
|
188
268
|
```
|
|
189
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
|
+
|
|
190
298
|
## Development runs
|
|
191
299
|
|
|
192
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/lib/rujira/api/common.rb
CHANGED
|
@@ -40,7 +40,7 @@ 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)
|
|
43
|
+
return @client.dispatch(@request) unless @client.wrap_responses
|
|
44
44
|
return self if @client.lazy
|
|
45
45
|
|
|
46
46
|
to_obj
|
|
@@ -81,7 +81,7 @@ module Rujira
|
|
|
81
81
|
Object.const_get(resource_class_name).new(@client, **response)
|
|
82
82
|
rescue NameError
|
|
83
83
|
raise "Resource class '#{resource_class_name}' not found. " \
|
|
84
|
-
'Please ensure the class exists or use
|
|
84
|
+
'Please ensure the class exists or use wrap_responses mode.'
|
|
85
85
|
end
|
|
86
86
|
end
|
|
87
87
|
|
|
@@ -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,8 +23,8 @@ 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
|
-
@
|
|
26
|
+
def initialize(url, debug: false, wrap_responses: false, lazy: false, log_level: 'error') # rubocop:disable Metrics/MethodLength
|
|
27
|
+
@wrap_responses = wrap_responses
|
|
28
28
|
@lazy = lazy
|
|
29
29
|
@uri = URI(url)
|
|
30
30
|
@debug = ENV.fetch('RUJIRA_DEBUG', debug.to_s) == 'true'
|
data/lib/rujira/request.rb
CHANGED
|
@@ -3,8 +3,16 @@
|
|
|
3
3
|
module Rujira
|
|
4
4
|
module Resource
|
|
5
5
|
class Common # rubocop:disable Style/Documentation
|
|
6
|
-
|
|
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
|
|
@@ -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
|
|
@@ -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
|
|
@@ -8,33 +8,18 @@ require 'json'
|
|
|
8
8
|
module Rujira
|
|
9
9
|
module Tasks
|
|
10
10
|
# TODO
|
|
11
|
-
class Jira
|
|
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
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
|
|
@@ -118,48 +103,6 @@ module Rujira
|
|
|
118
103
|
end
|
|
119
104
|
end
|
|
120
105
|
end
|
|
121
|
-
|
|
122
|
-
namespace :issue do # rubocop:disable Metrics/BlockLength
|
|
123
|
-
desc 'Create a issue'
|
|
124
|
-
task :create do |t|
|
|
125
|
-
options = fetch_options(%w[PROJECT_KEY SUMMARY DESCRIPTION ISSUETYPE], t.name)
|
|
126
|
-
abort 'ISSUETYPE must start with a capital letter' unless options[:issuetype].match?(/\A[A-Z]/)
|
|
127
|
-
|
|
128
|
-
result = client.Issue.create do
|
|
129
|
-
payload fields: {
|
|
130
|
-
project: { key: options[:project_key] },
|
|
131
|
-
summary: options[:summary],
|
|
132
|
-
issuetype: { name: options[:issuetype] },
|
|
133
|
-
description: options[:description]
|
|
134
|
-
}
|
|
135
|
-
end
|
|
136
|
-
puts JSON.pretty_generate(result)
|
|
137
|
-
end
|
|
138
|
-
|
|
139
|
-
desc 'Search issue by fields'
|
|
140
|
-
task :search do |t|
|
|
141
|
-
options = fetch_options(%w[JQL], t.name)
|
|
142
|
-
result = client.Search.get do
|
|
143
|
-
data jql: options[:jql]
|
|
144
|
-
end
|
|
145
|
-
result['issues'].each { |i| puts JSON.pretty_generate(i) }
|
|
146
|
-
end
|
|
147
|
-
|
|
148
|
-
desc 'Delete issue'
|
|
149
|
-
task :delete do |t|
|
|
150
|
-
options = fetch_options(%w[ISSUE_ID], t.name)
|
|
151
|
-
|
|
152
|
-
client.Issue.del options[:issue_id]
|
|
153
|
-
end
|
|
154
|
-
|
|
155
|
-
desc 'Example usage attaching in issue'
|
|
156
|
-
task :attach do |t|
|
|
157
|
-
options = fetch_options(%w[FILE ISSUE_ID], t.name)
|
|
158
|
-
|
|
159
|
-
result = client.Issue.attachments options[:issue_id], @options[:file]
|
|
160
|
-
puts JSON.pretty_generate(result)
|
|
161
|
-
end
|
|
162
|
-
end
|
|
163
106
|
end
|
|
164
107
|
end
|
|
165
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
|