rujira 0.4.0 → 0.5.1

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.
@@ -3,6 +3,8 @@
3
3
  module Rujira
4
4
  module Api
5
5
  # Provides access to Jira projects via the REST API.
6
+ # Allows creating, updating, retrieving, listing, and deleting projects,
7
+ # as well as retrieving project security levels.
6
8
  #
7
9
  # API reference:
8
10
  # https://docs.atlassian.com/software/jira/docs/api/REST/9.17.0/#api/2/project
@@ -15,21 +17,20 @@ module Rujira
15
17
  #
16
18
  # @example Create a project
17
19
  # client.Project.create do
18
- # payload {
20
+ # payload({
19
21
  # key: "TEST",
20
22
  # name: "Test Project",
21
23
  # projectTypeKey: "software",
22
24
  # projectTemplateKey: "com.atlassian.jira-core-project-templates:jira-core-project-management"
23
- # }
25
+ # })
24
26
  # end
25
- #
26
27
  def create(&block)
27
28
  builder do
28
29
  path 'project'
29
30
  method :post
30
31
  instance_eval(&block) if block_given?
31
32
  end
32
- run
33
+ call
33
34
  end
34
35
 
35
36
  # Updates an existing project.
@@ -40,9 +41,8 @@ module Rujira
40
41
  #
41
42
  # @example Update a project
42
43
  # client.Project.edit("TEST") do
43
- # payload { name: "Renamed Project" }
44
+ # payload({ name: "Renamed Project" })
44
45
  # end
45
- #
46
46
  def edit(id_or_key, &block)
47
47
  abort 'Project ID or KEY is required' if id_or_key.to_s.strip.empty?
48
48
  builder do
@@ -50,7 +50,7 @@ module Rujira
50
50
  method :put
51
51
  instance_eval(&block) if block_given?
52
52
  end
53
- run
53
+ call
54
54
  end
55
55
 
56
56
  # Retrieves a specific project by ID or key.
@@ -61,14 +61,13 @@ module Rujira
61
61
  #
62
62
  # @example Get a project
63
63
  # client.Project.get("TEST")
64
- #
65
64
  def get(id_or_key, &block)
66
65
  abort 'Project ID or KEY is required' if id_or_key.to_s.strip.empty?
67
66
  builder do
68
67
  path "project/#{id_or_key}"
69
68
  instance_eval(&block) if block_given?
70
69
  end
71
- run
70
+ call
72
71
  end
73
72
 
74
73
  # Lists all projects visible to the current user.
@@ -78,30 +77,30 @@ module Rujira
78
77
  #
79
78
  # @example List projects
80
79
  # client.Project.list
81
- #
82
80
  def list(&block)
83
81
  builder do
84
82
  path 'project'
85
83
  instance_eval(&block) if block_given?
86
84
  end
87
- run
85
+ call
88
86
  end
89
87
 
90
88
  # Deletes a project by ID or key.
91
89
  #
92
90
  # @param [String] id_or_key The project ID or key.
91
+ # @yield [builder] Optional block to configure additional request parameters.
93
92
  # @return [Object] The API response after deletion.
94
93
  #
95
94
  # @example Delete a project
96
95
  # client.Project.delete("TEST")
97
- #
98
- def delete(id_or_key)
96
+ def delete(id_or_key, &block)
99
97
  abort 'Project ID or KEY is required' if id_or_key.to_s.strip.empty?
100
98
  builder do
101
99
  method :delete
102
100
  path "project/#{id_or_key}"
101
+ instance_eval(&block) if block_given?
103
102
  end
104
- run
103
+ call
105
104
  end
106
105
 
107
106
  # Retrieves the security levels for a specific project.
@@ -112,14 +111,13 @@ module Rujira
112
111
  #
113
112
  # @example Get project security levels
114
113
  # client.Project.securitylevel("TEST")
115
- #
116
114
  def securitylevel(id_or_key, &block)
117
115
  abort 'Project ID or KEY is required' if id_or_key.to_s.strip.empty?
118
116
  builder do
119
117
  path "project/#{id_or_key}/securitylevel"
120
118
  instance_eval(&block) if block_given?
121
119
  end
122
- run
120
+ call
123
121
  end
124
122
  end
125
123
  end
@@ -11,22 +11,25 @@ module Rujira
11
11
  class Search < Common
12
12
  # Executes a search query against Jira issues.
13
13
  #
14
- # @yield [builder] Optional block to configure the request payload
15
- # (e.g., provide JQL, fields, pagination).
14
+ # @yield [builder] Optional block to configure the request payload,
15
+ # such as JQL query, fields to return, pagination, and sorting.
16
16
  # @return [Object] The API response containing matching issues.
17
17
  #
18
18
  # @example Search issues with JQL
19
19
  # client.Search.get do
20
- # payload jql: "project = TEST AND status = 'To Do'", maxResults: 10
20
+ # payload({
21
+ # jql: "project = TEST AND status = 'To Do'",
22
+ # maxResults: 10,
23
+ # fields: ["summary", "assignee", "status"]
24
+ # })
21
25
  # end
22
- #
23
26
  def get(&block)
24
27
  builder do
25
28
  path 'search'
26
29
  method :post
27
30
  instance_eval(&block) if block_given?
28
31
  end
29
- run
32
+ call
30
33
  end
31
34
  end
32
35
  end
@@ -3,7 +3,7 @@
3
3
  module Rujira
4
4
  module Api
5
5
  # Provides access to Jira server information via the REST API.
6
- # Retrieves details about the Jira server instance, including version and build info.
6
+ # Allows retrieving details about the Jira server instance, including version and build info.
7
7
  #
8
8
  # API reference:
9
9
  # https://docs.atlassian.com/software/jira/docs/api/REST/9.17.0/#api/2/serverInfo
@@ -11,16 +11,18 @@ module Rujira
11
11
  class ServerInfo < Common
12
12
  # Retrieves Jira server information.
13
13
  #
14
+ # @yield [builder] Optional block to configure additional request parameters.
14
15
  # @return [Object] The API response containing server details.
15
16
  #
16
- # @example Get server info
17
- # client.Server_info.get
17
+ # @example Get Jira server information
18
+ # client.ServerInfo.get
18
19
  #
19
- def get
20
+ def get(&block)
20
21
  builder do
21
22
  path 'serverInfo'
23
+ instance_eval(&block) if block_given?
22
24
  end
23
- run
25
+ call
24
26
  end
25
27
  end
26
28
  end
@@ -37,7 +37,7 @@ module Rujira
37
37
  method :post
38
38
  instance_eval(&block) if block_given?
39
39
  end
40
- run
40
+ call
41
41
  end
42
42
 
43
43
  # Updates an existing sprint partially.
@@ -53,7 +53,7 @@ module Rujira
53
53
  #
54
54
  def update(id, &block)
55
55
  abort 'Sprint ID is required' if id.to_s.strip.empty?
56
- raise ArgumentError, 'block is required' unless block
56
+ raise ArgumentError, 'Block is required' unless block
57
57
 
58
58
  builder do
59
59
  path "sprint/#{id}"
@@ -61,7 +61,7 @@ module Rujira
61
61
  method :post
62
62
  instance_eval(&block)
63
63
  end
64
- run
64
+ call
65
65
  end
66
66
 
67
67
  # Replaces an existing sprint.
@@ -77,7 +77,7 @@ module Rujira
77
77
  #
78
78
  def replace(id, &block)
79
79
  abort 'Sprint ID is required' if id.to_s.strip.empty?
80
- raise ArgumentError, 'block is required' unless block
80
+ raise ArgumentError, 'Block is required' unless block
81
81
 
82
82
  builder do
83
83
  path "sprint/#{id}"
@@ -85,79 +85,101 @@ module Rujira
85
85
  method :put
86
86
  instance_eval(&block)
87
87
  end
88
- run
88
+ call
89
89
  end
90
90
 
91
91
  # Retrieves details of a specific sprint.
92
92
  #
93
93
  # @param [Integer] id The sprint ID.
94
+ # @yield [builder] Optional block to configure the request.
94
95
  # @return [Object] The API response containing sprint details.
95
96
  #
96
- def get(id)
97
+ # @example Get sprint details
98
+ # client.Sprint.get(1)
99
+ #
100
+ def get(id, &block)
97
101
  abort 'Sprint ID is required' if id.to_s.strip.empty?
98
102
  builder do
99
103
  path "sprint/#{id}"
104
+ instance_eval(&block) if block_given?
100
105
  end
101
- run
106
+ call
102
107
  end
103
108
 
104
109
  # Retrieves all issues in a sprint.
105
110
  #
106
111
  # @param [Integer] id The sprint ID.
107
- # @return [Object] The API response containing issues.
112
+ # @yield [builder] Optional block to configure the request.
113
+ # @return [Object] The API response containing sprint issues.
114
+ #
115
+ # @example Get issues in sprint
116
+ # client.Sprint.get_issue(1)
108
117
  #
109
- def get_issue(id)
118
+ def get_issue(id, &block)
110
119
  abort 'Sprint ID is required' if id.to_s.strip.empty?
111
120
  builder do
112
121
  path "sprint/#{id}/issue"
122
+ instance_eval(&block) if block_given?
113
123
  end
114
- run
124
+ call
115
125
  end
116
126
 
117
127
  # Deletes a sprint.
118
128
  #
119
129
  # @param [Integer] id The sprint ID.
130
+ # @yield [builder] Optional block to configure the request.
120
131
  # @return [Object] The API response after deletion.
121
132
  #
122
- def delete(id)
133
+ # @example Delete sprint
134
+ # client.Sprint.delete(1)
135
+ #
136
+ def delete(id, &block)
123
137
  abort 'Sprint ID is required' if id.to_s.strip.empty?
124
138
  builder do
125
139
  method :delete
126
140
  path "sprint/#{id}"
141
+ instance_eval(&block) if block_given?
127
142
  end
128
- run
143
+ call
129
144
  end
130
145
 
131
146
  # Retrieves all properties of a sprint.
132
147
  #
133
148
  # @param [Integer] id The sprint ID.
149
+ # @yield [builder] Optional block to configure the request.
134
150
  # @return [Object] The API response containing sprint properties.
135
151
  #
136
- def properties(id)
152
+ # @example Get sprint properties
153
+ # client.Sprint.properties(1)
154
+ #
155
+ def properties(id, &block)
137
156
  abort 'Sprint ID is required' if id.to_s.strip.empty?
138
157
  builder do
139
158
  path "sprint/#{id}/properties"
159
+ instance_eval(&block) if block_given?
140
160
  end
141
- run
161
+ call
142
162
  end
143
163
 
144
164
  # Adds issues to a sprint.
145
165
  #
146
166
  # @param [Integer] id The sprint ID.
147
167
  # @param [Array<Integer>] issues List of issue IDs to add to the sprint.
168
+ # @yield [builder] Optional block to configure the request.
148
169
  # @return [Object] The API response after adding issues.
149
170
  #
150
- # @example Add issues to a sprint
171
+ # @example Add issues to sprint
151
172
  # client.Sprint.issue(1, [101, 102])
152
173
  #
153
- def issue(id, issues)
174
+ def issue(id, issues, &block)
154
175
  abort 'Sprint ID is required' if id.to_s.strip.empty?
155
176
  builder do
156
177
  method :post
157
178
  path "sprint/#{id}/issue"
158
179
  payload issues: issues
180
+ instance_eval(&block) if block_given?
159
181
  end
160
- run
182
+ call
161
183
  end
162
184
  end
163
185
  end
data/lib/rujira/client.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'logger'
4
+
3
5
  module Rujira
4
6
  # Main Jira API client.
5
7
  # Provides access to Jira resources via method_missing delegation to API classes.
@@ -9,8 +11,7 @@ module Rujira
9
11
  # client.issue.get("TEST-123")
10
12
  #
11
13
  class Client
12
- # @return [Rujira::Request] The current request object being configured
13
- attr_accessor :request
14
+ attr_reader :logger, :dispatchable
14
15
 
15
16
  # Initializes a new Jira client.
16
17
  #
@@ -20,11 +21,25 @@ module Rujira
20
21
  # @example Initialize client
21
22
  # client = Rujira::Client.new("https://jira.example.com", debug: true)
22
23
  #
23
- def initialize(url, debug: false)
24
+ def initialize(url, debug: false, dispatchable: true, log_level: 'error') # rubocop:disable Metrics/MethodLength
25
+ @dispatchable = dispatchable
24
26
  @uri = URI(url)
25
27
  @debug = ENV.fetch('RUJIRA_DEBUG', debug.to_s) == 'true'
26
28
  @raise_error = false
27
- @request = Request.new
29
+ @logger ||= Logger.new($stdout)
30
+
31
+ log_levels = {
32
+ 'debug' => Logger::DEBUG,
33
+ 'info' => Logger::INFO,
34
+ 'warn' => Logger::WARN,
35
+ 'error' => Logger::ERROR,
36
+ 'fatal' => Logger::FATAL
37
+ }
38
+
39
+ @logger.level = log_levels.fetch(
40
+ ENV.fetch('LOG_LEVEL', log_level).downcase,
41
+ Logger::ERROR
42
+ )
28
43
  end
29
44
 
30
45
  # Dynamically instantiates the appropriate API resource class.
@@ -36,25 +51,13 @@ module Rujira
36
51
  # @example Access an API resource
37
52
  # client.issue.get("TEST-123")
38
53
  #
39
- def method_missing(method_name, ...)
54
+ def method_missing(method_name)
40
55
  resource_class = Rujira::Api.const_get(method_name.to_s)
41
- resource_class.new(self, ...)
56
+ resource_class.new(self)
42
57
  rescue NameError
43
58
  super
44
59
  end
45
60
 
46
- # Options for Faraday connection.
47
- #
48
- # @return [Hash] Options including URL, headers, and params
49
- #
50
- def options
51
- {
52
- url: @uri,
53
- headers: @request.headers,
54
- params: @request.params
55
- }
56
- end
57
-
58
61
  # Checks if a resource class exists for method_missing.
59
62
  #
60
63
  # @param [Symbol] method_name Method name to check
@@ -70,16 +73,19 @@ module Rujira
70
73
  # @return [Object] The API response body if successful
71
74
  # @raise [RuntimeError] If the request fails or method is unsupported
72
75
  #
73
- def dispatch # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
74
- unless %i[get delete head post put patch].include?(@request.method)
75
- raise "method #{@request.method} not supported"
76
- end
76
+ def dispatch(request) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
77
+ raise "method #{request.method} not supported" unless %i[get delete head post put patch].include?(request.method)
77
78
 
78
79
  begin
79
- args = [@request.path]
80
- args << @request.payload if %i[post put patch].include?(@request.method)
80
+ args = [request.path]
81
+ args << request.payload if %i[post put patch].include?(request.method)
81
82
 
82
- response = connection.public_send(@request.method, *args)
83
+ options = {
84
+ url: @uri,
85
+ headers: request.headers,
86
+ params: request.params
87
+ }
88
+ response = connection(options, request.authorization).public_send(request.method, *args)
83
89
 
84
90
  if response.success?
85
91
  response.body
@@ -96,14 +102,14 @@ module Rujira
96
102
  #
97
103
  # @return [Faraday::Connection] Configured Faraday connection
98
104
  #
99
- def connection
105
+ def connection(options, authorization)
100
106
  Faraday.new(options) do |builder|
101
- builder.request :authorization, *@request.authorization if @request.authorization
107
+ builder.request :authorization, *authorization if authorization
102
108
  builder.request :multipart, flat_encode: true
103
109
  builder.request :json
104
110
  builder.response :json
105
111
  builder.response :raise_error if @raise_error
106
- builder.response :logger if @debug
112
+ builder.response :logger, @logger if @debug
107
113
  end
108
114
  end
109
115
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rujira
4
- VERSION = '0.4.0'
4
+ VERSION = '0.5.1'
5
5
  end
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.4.0
4
+ version: 0.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrey Semenov