jira_client 1.0.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 (67) hide show
  1. data/.gitignore +19 -0
  2. data/.rspec +2 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +29 -0
  6. data/Rakefile +1 -0
  7. data/jira_client.gemspec +27 -0
  8. data/lib/jira_client.rb +121 -0
  9. data/lib/jira_client/api/comments.rb +19 -0
  10. data/lib/jira_client/api/issues.rb +62 -0
  11. data/lib/jira_client/api/projects.rb +19 -0
  12. data/lib/jira_client/api/server.rb +15 -0
  13. data/lib/jira_client/api/statuses.rb +20 -0
  14. data/lib/jira_client/api/users.rb +18 -0
  15. data/lib/jira_client/api/utils.rb +25 -0
  16. data/lib/jira_client/api/worklogs.rb +26 -0
  17. data/lib/jira_client/base.rb +54 -0
  18. data/lib/jira_client/comment.rb +12 -0
  19. data/lib/jira_client/configuration.rb +27 -0
  20. data/lib/jira_client/core_ext/string.rb +7 -0
  21. data/lib/jira_client/error/bad_request.rb +5 -0
  22. data/lib/jira_client/error/configuration_error.rb +5 -0
  23. data/lib/jira_client/error/issue_error.rb +5 -0
  24. data/lib/jira_client/error/resource_not_found.rb +5 -0
  25. data/lib/jira_client/error/unauthorized.rb +5 -0
  26. data/lib/jira_client/issue.rb +26 -0
  27. data/lib/jira_client/project.rb +5 -0
  28. data/lib/jira_client/server_info.rb +11 -0
  29. data/lib/jira_client/status.rb +7 -0
  30. data/lib/jira_client/timetracking.rb +6 -0
  31. data/lib/jira_client/user.rb +10 -0
  32. data/lib/jira_client/version.rb +3 -0
  33. data/lib/jira_client/worklog.rb +10 -0
  34. data/spec/fixtures/admin.json +17 -0
  35. data/spec/fixtures/basic_issue.json +6 -0
  36. data/spec/fixtures/comment.json +23 -0
  37. data/spec/fixtures/comments.json +30 -0
  38. data/spec/fixtures/invalid_assignee.json +6 -0
  39. data/spec/fixtures/invalid_comment.json +6 -0
  40. data/spec/fixtures/invalid_jql.json +6 -0
  41. data/spec/fixtures/issue_with_comments.json +33 -0
  42. data/spec/fixtures/issue_with_description.json +10 -0
  43. data/spec/fixtures/issue_with_status.json +15 -0
  44. data/spec/fixtures/issue_with_timetracking.json +16 -0
  45. data/spec/fixtures/issue_with_worklogs.json +34 -0
  46. data/spec/fixtures/issues.json +28 -0
  47. data/spec/fixtures/my_certificate.pem +52 -0
  48. data/spec/fixtures/no_issues_found.json +6 -0
  49. data/spec/fixtures/project.json +10 -0
  50. data/spec/fixtures/projects.json +22 -0
  51. data/spec/fixtures/server_info.json +14 -0
  52. data/spec/fixtures/status.json +7 -0
  53. data/spec/fixtures/statuses.json +16 -0
  54. data/spec/fixtures/user_doesnt_exist.json +6 -0
  55. data/spec/fixtures/users.json +22 -0
  56. data/spec/fixtures/worklog.json +31 -0
  57. data/spec/jira_client/api/comments_spec.rb +59 -0
  58. data/spec/jira_client/api/issues_spec.rb +314 -0
  59. data/spec/jira_client/api/projects_spec.rb +55 -0
  60. data/spec/jira_client/api/server_spec.rb +31 -0
  61. data/spec/jira_client/api/statuses_spec.rb +69 -0
  62. data/spec/jira_client/api/users_spec.rb +56 -0
  63. data/spec/jira_client/api/worklogs_spec.rb +86 -0
  64. data/spec/jira_client/configuration_spec.rb +78 -0
  65. data/spec/jira_client_spec.rb +49 -0
  66. data/spec/spec_helper.rb +56 -0
  67. metadata +226 -0
@@ -0,0 +1,54 @@
1
+ require "jira_client/core_ext/string"
2
+
3
+ module JiraClient
4
+ class Base
5
+ class << self
6
+ # Initialize class variable if not set
7
+ def conversions
8
+ @conversions ||= {}
9
+ end
10
+
11
+ def convert(attribute, conversion)
12
+ if conversion.instance_of? Proc
13
+ conversions[attribute] = conversion
14
+ elsif conversion < JiraClient::Base
15
+ conversions[attribute] = lambda {|v| conversion.from_response(v)}
16
+ end
17
+ end
18
+
19
+ def attr_reader(*attrs)
20
+ mod = Module.new do
21
+ attrs.each do |attribute|
22
+ define_method attribute do
23
+ @attrs[attribute.to_sym]
24
+ end
25
+ define_method "#{attribute}?" do
26
+ !!@attrs[attribute.to_sym]
27
+ end
28
+ end
29
+ end
30
+ include mod
31
+ end
32
+
33
+ def from_response(attrs={})
34
+ return unless attrs
35
+ new(attrs)
36
+ end
37
+
38
+ end
39
+
40
+ def initialize(attrs={})
41
+ self.class.conversions.each do |key, value|
42
+ if attrs.has_key? key
43
+ if attrs[key].kind_of? Array
44
+ attrs[key] = attrs[key].map {|elem| value.call(elem)}
45
+ else
46
+ attrs[key] = value.call(attrs[key])
47
+ end
48
+ end
49
+ end
50
+ @attrs = attrs
51
+ end
52
+
53
+ end
54
+ end
@@ -0,0 +1,12 @@
1
+ require "jira_client/user"
2
+
3
+ module JiraClient
4
+ class Comment < JiraClient::Base
5
+ attr_reader :id, :author, :body, :update_author, :created, :updated
6
+
7
+ convert :author, JiraClient::User
8
+ convert :update_author, JiraClient::User
9
+ convert :created, lambda {|value| DateTime.parse(value)}
10
+ convert :updated, lambda {|value| DateTime.parse(value)}
11
+ end
12
+ end
@@ -0,0 +1,27 @@
1
+ module JiraClient
2
+ class Configuration
3
+ attr_accessor :base_url, :api_path, :port, :proxy, :username, :password, :certificate, :certificate_passphrase
4
+
5
+ def initialize
6
+ @base_url = nil
7
+ @port = nil
8
+ @proxy = nil
9
+ @api_path = "/rest/api/2"
10
+ @username = nil
11
+ @password = nil
12
+ @certificate = nil
13
+ @certificate_passphrase = nil
14
+ end
15
+
16
+ def full_url
17
+ if @base_url.nil? or @api_path.nil?
18
+ raise JiraClient::Error::ConfigurationError, "Invalid configuration. Run JiraClient.configure."
19
+ end
20
+ result = @base_url.gsub(/\/\z/, '')
21
+ result += ":#{@port}" unless @port.nil?
22
+ result += @api_path
23
+ result
24
+ end
25
+
26
+ end
27
+ end
@@ -0,0 +1,7 @@
1
+ class String
2
+
3
+ def underscore
4
+ self.gsub(/::/, '/').gsub(/([a-z]+)([A-Z])/, '\1_\2').gsub(/([a-z\d])([A-Z])/, '\1\2').tr("-", "_").downcase
5
+ end
6
+
7
+ end
@@ -0,0 +1,5 @@
1
+ module JiraClient
2
+ module Error
3
+ class BadRequest < StandardError; end
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ module JiraClient
2
+ module Error
3
+ class ConfigurationError < ::ArgumentError; end
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ module JiraClient
2
+ module Error
3
+ class IssueError < StandardError; end
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ module JiraClient
2
+ module Error
3
+ class ResourceNotFound < StandardError; end
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ module JiraClient
2
+ module Error
3
+ class Unauthorized < StandardError; end
4
+ end
5
+ end
@@ -0,0 +1,26 @@
1
+ require "jira_client/status"
2
+ require "jira_client/timetracking"
3
+ require "jira_client/project"
4
+ require "jira_client/worklog"
5
+
6
+ module JiraClient
7
+ class Issue < JiraClient::Base
8
+ attr_reader :key, :description, :summary, :status, :timetracking, :project, :worklog, :comment
9
+
10
+ convert :status, JiraClient::Status
11
+ convert :timetracking, JiraClient::Timetracking
12
+ convert :comment, JiraClient::Comment
13
+ convert :project, JiraClient::Project
14
+ convert :worklog, JiraClient::Worklog
15
+
16
+ class << self
17
+
18
+ def from_response(params)
19
+ # Make values nested in the :fields key top-level values
20
+ params.merge!(params[:fields]).delete :fields if params.has_key? :fields
21
+ super(params)
22
+ end
23
+
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,5 @@
1
+ module JiraClient
2
+ class Project < JiraClient::Base
3
+ attr_reader :name, :key
4
+ end
5
+ end
@@ -0,0 +1,11 @@
1
+ require "time"
2
+ require "jira_client/base"
3
+
4
+ module JiraClient
5
+ class ServerInfo < JiraClient::Base
6
+ attr_reader :version, :base_url, :build_number, :build_date, :server_title, :server_time
7
+
8
+ convert :server_time, lambda {|value| Time.parse(value)}
9
+ convert :build_date, lambda {|value| Time.parse(value)}
10
+ end
11
+ end
@@ -0,0 +1,7 @@
1
+ module JiraClient
2
+ class Status < JiraClient::Base
3
+ OPEN = 1; CLOSE = 2; START_PROGRESS = 4; REOPEN = 3; RESOLVE = 5;
4
+
5
+ attr_reader :id, :name, :description
6
+ end
7
+ end
@@ -0,0 +1,6 @@
1
+ module JiraClient
2
+ class Timetracking < JiraClient::Base
3
+ attr_reader :original_estimate, :remaining_estimate, :time_spent, :original_estimate_seconds,
4
+ :remaining_estimate_seconds, :time_spent_seconds
5
+ end
6
+ end
@@ -0,0 +1,10 @@
1
+ module JiraClient
2
+ class User < JiraClient::Base
3
+ attr_reader :display_name, :email_address, :name
4
+
5
+ def active?
6
+ @attrs[:active] == true
7
+ end
8
+
9
+ end
10
+ end
@@ -0,0 +1,3 @@
1
+ module JiraClient
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,10 @@
1
+ module JiraClient
2
+ class Worklog < JiraClient::Base
3
+ attr_reader :time_spent, :comment, :author, :update_author, :started, :time_spent_seconds
4
+
5
+ convert :author, JiraClient::User
6
+ convert :update_author, JiraClient::User
7
+ convert :started, lambda {|value| Time.parse(value)}
8
+ convert :time_spent_seconds, lambda {|value| value.to_i }
9
+ end
10
+ end
@@ -0,0 +1,17 @@
1
+ {
2
+ "self": "http://localhost:2990/jira/rest/api/2/user?username=admin",
3
+ "name": "admin",
4
+ "emailAddress": "admin@example.com",
5
+ "avatarUrls": {
6
+ "16x16": "http://localhost:2990/jira/secure/useravatar?size=small&avatarId=10122",
7
+ "48x48": "http://localhost:2990/jira/secure/useravatar?avatarId=10122"
8
+ },
9
+ "displayName": "admin",
10
+ "active": true,
11
+ "timeZone": "Europe/London",
12
+ "groups": {
13
+ "size": 3,
14
+ "items": []
15
+ },
16
+ "expand": "groups"
17
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "expand": "renderedFields,names,schema,transitions,operations,editmeta,changelog",
3
+ "id": "4321",
4
+ "self": "https://example.jira.com/rest/api/2/issue/4321",
5
+ "key": "PROJECT-1234"
6
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "self": "http://www.example.com/jira/rest/api/2.0/issue/10010/comment/10000",
3
+ "id": "10000",
4
+ "author": {
5
+ "self": "http://www.example.com/jira/rest/api/2.0/user?username=fred",
6
+ "name": "fred",
7
+ "displayName": "Fred F. User",
8
+ "active": false
9
+ },
10
+ "body": "This is a comment",
11
+ "updateAuthor": {
12
+ "self": "http://www.example.com/jira/rest/api/2.0/user?username=fred",
13
+ "name": "fred",
14
+ "displayName": "Fred F. User",
15
+ "active": false
16
+ },
17
+ "created": "2012-02-15T17:34:37.268-0600",
18
+ "updated": "2012-02-15T17:34:37.269-0600",
19
+ "visibility": {
20
+ "type": "role",
21
+ "value": "Administrators"
22
+ }
23
+ }
@@ -0,0 +1,30 @@
1
+ {
2
+ "startAt": 0,
3
+ "maxResults": 1,
4
+ "total": 1,
5
+ "comments": [
6
+ {
7
+ "self": "http://www.example.com/jira/rest/api/2.0/issue/10010/comment/10000",
8
+ "id": "10000",
9
+ "author": {
10
+ "self": "http://www.example.com/jira/rest/api/2.0/user?username=fred",
11
+ "name": "fred",
12
+ "displayName": "Fred F. User",
13
+ "active": false
14
+ },
15
+ "body": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque eget venenatis elit. Duis eu justo eget augue iaculis fermentum. Sed semper quam laoreet nisi egestas at posuere augue semper.",
16
+ "updateAuthor": {
17
+ "self": "http://www.example.com/jira/rest/api/2.0/user?username=fred",
18
+ "name": "fred",
19
+ "displayName": "Fred F. User",
20
+ "active": false
21
+ },
22
+ "created": "2012-02-15T17:34:37.268-0600",
23
+ "updated": "2012-02-15T17:34:37.269-0600",
24
+ "visibility": {
25
+ "type": "role",
26
+ "value": "Administrators"
27
+ }
28
+ }
29
+ ]
30
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "errorMessages": [],
3
+ "errors": {
4
+ "assignee": "User 'fwafawf' does not exist."
5
+ }
6
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "errorMessages": [],
3
+ "errors": {
4
+ "comment": "Comment body can not be empty!"
5
+ }
6
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "errorMessages": [
3
+ "The value 'DOESNT_EXIST' does not exist for the field 'project'."
4
+ ],
5
+ "errors": {}
6
+ }
@@ -0,0 +1,33 @@
1
+ {
2
+ "expand": "renderedFields,names,schema,transitions,operations,editmeta,changelog",
3
+ "id": "4321",
4
+ "self": "https://example.jira.com/rest/api/2/issue/4321",
5
+ "key": "PROJECT-1234",
6
+ "fields": {
7
+ "comment": [
8
+ {
9
+ "self": "http://www.example.com/jira/rest/api/2.0/issue/10010/comment/10000",
10
+ "id": "10000",
11
+ "author": {
12
+ "self": "http://www.example.com/jira/rest/api/2.0/user?username=fred",
13
+ "name": "fred",
14
+ "displayName": "Fred F. User",
15
+ "active": false
16
+ },
17
+ "body": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque eget venenatis elit. Duis eu justo eget augue iaculis fermentum. Sed semper quam laoreet nisi egestas at posuere augue semper.",
18
+ "updateAuthor": {
19
+ "self": "http://www.example.com/jira/rest/api/2.0/user?username=fred",
20
+ "name": "fred",
21
+ "displayName": "Fred F. User",
22
+ "active": false
23
+ },
24
+ "created": "2012-02-15T17:34:37.268-0600",
25
+ "updated": "2012-02-15T17:34:37.269-0600",
26
+ "visibility": {
27
+ "type": "role",
28
+ "value": "Administrators"
29
+ }
30
+ }
31
+ ]
32
+ }
33
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "expand": "renderedFields,names,schema,transitions,operations,editmeta,changelog",
3
+ "id": "4321",
4
+ "self": "https://example.jira.com/rest/api/2/issue/4321",
5
+ "key": "PROJECT-1235",
6
+ "fields": {
7
+ "summary": "This is an issue summary",
8
+ "description": "This is a description"
9
+ }
10
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "expand": "renderedFields,names,schema,transitions,operations,editmeta,changelog",
3
+ "id": "4321",
4
+ "self": "https://example.jira.com/rest/api/2/issue/4321",
5
+ "key": "PROJECT-1236",
6
+ "fields": {
7
+ "status": {
8
+ "self": "https://example.jira.com/jira/rest/api/2.0/status/10000",
9
+ "description": "The issue is currently being worked on.",
10
+ "iconUrl": "https://example.jira.com/images/icons/progress.gif",
11
+ "name": "In Progress",
12
+ "id": "10000"
13
+ }
14
+ }
15
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "expand": "renderedFields,names,schema,transitions,operations,editmeta,changelog",
3
+ "id": "4321",
4
+ "self": "https://example.jira.com/rest/api/2/issue/4321",
5
+ "key": "PROJECT-1234",
6
+ "fields": {
7
+ "timetracking": {
8
+ "originalEstimate": "10m",
9
+ "remainingEstimate": "3m",
10
+ "timeSpent": "6m",
11
+ "originalEstimateSeconds": 600,
12
+ "remainingEstimateSeconds": 200,
13
+ "timeSpentSeconds": 400
14
+ }
15
+ }
16
+ }
@@ -0,0 +1,34 @@
1
+ {
2
+ "expand": "renderedFields,names,schema,transitions,operations,editmeta,changelog",
3
+ "id": "4321",
4
+ "self": "https://example.jira.com/rest/api/2/issue/4321",
5
+ "key": "PROJECT-1234",
6
+ "fields": {
7
+ "worklog": [
8
+ {
9
+ "self": "http://www.example.com/jira/rest/api/2.0/issue/10010/worklog/10000",
10
+ "author": {
11
+ "self": "http://www.example.com/jira/rest/api/2.0/user?username=fred",
12
+ "name": "fred",
13
+ "displayName": "Fred F. User",
14
+ "active": false
15
+ },
16
+ "updateAuthor": {
17
+ "self": "http://www.example.com/jira/rest/api/2.0/user?username=fred",
18
+ "name": "fred",
19
+ "displayName": "Fred F. User",
20
+ "active": false
21
+ },
22
+ "comment": "I did some work here.",
23
+ "started": "2012-02-15T17:34:37.937-0600",
24
+ "timeSpent": "3h 20m",
25
+ "timeSpentSeconds": 12000,
26
+ "id": "100028",
27
+ "visibility": {
28
+ "type": "group",
29
+ "value": "jira-developers"
30
+ }
31
+ }
32
+ ]
33
+ }
34
+ }