jira-ruby-dmg 0.1.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +10 -0
- data/.travis.yml +6 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +46 -0
- data/README.rdoc +309 -0
- data/Rakefile +28 -0
- data/example.rb +119 -0
- data/http-basic-example.rb +112 -0
- data/jira-ruby-dmg.gemspec +28 -0
- data/lib/jira/base.rb +497 -0
- data/lib/jira/base_factory.rb +49 -0
- data/lib/jira/client.rb +165 -0
- data/lib/jira/has_many_proxy.rb +43 -0
- data/lib/jira/http_client.rb +69 -0
- data/lib/jira/http_error.rb +16 -0
- data/lib/jira/oauth_client.rb +84 -0
- data/lib/jira/railtie.rb +10 -0
- data/lib/jira/request_client.rb +18 -0
- data/lib/jira/resource/attachment.rb +12 -0
- data/lib/jira/resource/comment.rb +14 -0
- data/lib/jira/resource/component.rb +10 -0
- data/lib/jira/resource/field.rb +10 -0
- data/lib/jira/resource/filter.rb +15 -0
- data/lib/jira/resource/issue.rb +76 -0
- data/lib/jira/resource/issuetype.rb +10 -0
- data/lib/jira/resource/priority.rb +10 -0
- data/lib/jira/resource/project.rb +31 -0
- data/lib/jira/resource/status.rb +10 -0
- data/lib/jira/resource/transition.rb +33 -0
- data/lib/jira/resource/user.rb +14 -0
- data/lib/jira/resource/version.rb +10 -0
- data/lib/jira/resource/worklog.rb +16 -0
- data/lib/jira/tasks.rb +0 -0
- data/lib/jira/version.rb +3 -0
- data/lib/jira.rb +33 -0
- data/lib/tasks/generate.rake +18 -0
- data/spec/integration/attachment_spec.rb +23 -0
- data/spec/integration/comment_spec.rb +55 -0
- data/spec/integration/component_spec.rb +42 -0
- data/spec/integration/field_spec.rb +35 -0
- data/spec/integration/issue_spec.rb +94 -0
- data/spec/integration/issuetype_spec.rb +26 -0
- data/spec/integration/priority_spec.rb +27 -0
- data/spec/integration/project_spec.rb +56 -0
- data/spec/integration/status_spec.rb +27 -0
- data/spec/integration/transition_spec.rb +52 -0
- data/spec/integration/user_spec.rb +25 -0
- data/spec/integration/version_spec.rb +43 -0
- data/spec/integration/worklog_spec.rb +55 -0
- data/spec/jira/base_factory_spec.rb +46 -0
- data/spec/jira/base_spec.rb +586 -0
- data/spec/jira/client_spec.rb +188 -0
- data/spec/jira/has_many_proxy_spec.rb +45 -0
- data/spec/jira/http_client_spec.rb +109 -0
- data/spec/jira/http_error_spec.rb +25 -0
- data/spec/jira/oauth_client_spec.rb +111 -0
- data/spec/jira/request_client_spec.rb +14 -0
- data/spec/jira/resource/attachment_spec.rb +20 -0
- data/spec/jira/resource/filter_spec.rb +97 -0
- data/spec/jira/resource/issue_spec.rb +107 -0
- data/spec/jira/resource/project_factory_spec.rb +13 -0
- data/spec/jira/resource/project_spec.rb +70 -0
- data/spec/jira/resource/worklog_spec.rb +24 -0
- data/spec/mock_responses/attachment/10000.json +20 -0
- data/spec/mock_responses/component/10000.invalid.put.json +5 -0
- data/spec/mock_responses/component/10000.json +39 -0
- data/spec/mock_responses/component/10000.put.json +39 -0
- data/spec/mock_responses/component.post.json +28 -0
- data/spec/mock_responses/field/1.json +15 -0
- data/spec/mock_responses/field.json +32 -0
- data/spec/mock_responses/issue/10002/comment/10000.json +29 -0
- data/spec/mock_responses/issue/10002/comment/10000.put.json +29 -0
- data/spec/mock_responses/issue/10002/comment.json +65 -0
- data/spec/mock_responses/issue/10002/comment.post.json +29 -0
- data/spec/mock_responses/issue/10002/transitions.json +49 -0
- data/spec/mock_responses/issue/10002/transitions.post.json +1 -0
- data/spec/mock_responses/issue/10002/worklog/10000.json +31 -0
- data/spec/mock_responses/issue/10002/worklog/10000.put.json +30 -0
- data/spec/mock_responses/issue/10002/worklog.json +98 -0
- data/spec/mock_responses/issue/10002/worklog.post.json +30 -0
- data/spec/mock_responses/issue/10002.invalid.put.json +6 -0
- data/spec/mock_responses/issue/10002.json +126 -0
- data/spec/mock_responses/issue/10002.put.missing_field_update.json +6 -0
- data/spec/mock_responses/issue.json +1108 -0
- data/spec/mock_responses/issue.post.json +5 -0
- data/spec/mock_responses/issuetype/5.json +8 -0
- data/spec/mock_responses/issuetype.json +42 -0
- data/spec/mock_responses/priority/1.json +8 -0
- data/spec/mock_responses/priority.json +42 -0
- data/spec/mock_responses/project/SAMPLEPROJECT.issues.json +1108 -0
- data/spec/mock_responses/project/SAMPLEPROJECT.json +84 -0
- data/spec/mock_responses/project.json +12 -0
- data/spec/mock_responses/status/1.json +7 -0
- data/spec/mock_responses/status.json +37 -0
- data/spec/mock_responses/user_username=admin.json +17 -0
- data/spec/mock_responses/version/10000.invalid.put.json +5 -0
- data/spec/mock_responses/version/10000.json +11 -0
- data/spec/mock_responses/version/10000.put.json +7 -0
- data/spec/mock_responses/version.post.json +7 -0
- data/spec/spec_helper.rb +22 -0
- data/spec/support/clients_helper.rb +16 -0
- data/spec/support/matchers/have_attributes.rb +11 -0
- data/spec/support/matchers/have_many.rb +9 -0
- data/spec/support/matchers/have_one.rb +5 -0
- data/spec/support/shared_examples/integration.rb +190 -0
- metadata +301 -0
@@ -0,0 +1,43 @@
|
|
1
|
+
#
|
2
|
+
# Whenever a collection from a has_many relationship is accessed, an instance
|
3
|
+
# of this class is returned. This instance wraps the Array of instances in
|
4
|
+
# the collection with an extra build method, which allows new instances to be
|
5
|
+
# built on the collection with the correct properties.
|
6
|
+
#
|
7
|
+
# In practice, instances of this class behave exactly like an Array.
|
8
|
+
#
|
9
|
+
class JIRA::HasManyProxy
|
10
|
+
|
11
|
+
attr_reader :target_class, :parent
|
12
|
+
attr_accessor :collection
|
13
|
+
|
14
|
+
def initialize(parent, target_class, collection = [])
|
15
|
+
@parent = parent
|
16
|
+
@target_class = target_class
|
17
|
+
@collection = collection
|
18
|
+
end
|
19
|
+
|
20
|
+
# Builds an instance of this class with the correct parent.
|
21
|
+
# For example, issue.comments.build(attrs) will initialize a
|
22
|
+
# comment as follows:
|
23
|
+
#
|
24
|
+
# JIRA::Resource::Comment.new(issue.client,
|
25
|
+
# :attrs => attrs,
|
26
|
+
# :issue => issue)
|
27
|
+
def build(attrs = {})
|
28
|
+
resource = target_class.new(parent.client, :attrs => attrs, parent.to_sym => parent)
|
29
|
+
collection << resource
|
30
|
+
resource
|
31
|
+
end
|
32
|
+
|
33
|
+
# Forces an HTTP request to fetch all instances of the target class that
|
34
|
+
# are associated with the parent
|
35
|
+
def all
|
36
|
+
target_class.all(parent.client, parent.to_sym => parent)
|
37
|
+
end
|
38
|
+
|
39
|
+
# Delegate any missing methods to the collection that this proxy wraps
|
40
|
+
def method_missing(method_name, *args, &block)
|
41
|
+
collection.send(method_name, *args, &block)
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'net/https'
|
3
|
+
require 'cgi/cookie'
|
4
|
+
|
5
|
+
module JIRA
|
6
|
+
class HttpClient < RequestClient
|
7
|
+
|
8
|
+
DEFAULT_OPTIONS = {
|
9
|
+
:username => '',
|
10
|
+
:password => ''
|
11
|
+
}
|
12
|
+
|
13
|
+
attr_reader :options
|
14
|
+
|
15
|
+
def initialize(options)
|
16
|
+
@options = DEFAULT_OPTIONS.merge(options)
|
17
|
+
@cookies = {}
|
18
|
+
end
|
19
|
+
|
20
|
+
def make_request(http_method, path, body='', headers={})
|
21
|
+
request = Net::HTTP.const_get(http_method.to_s.capitalize).new(path, headers)
|
22
|
+
request.body = body unless body.nil?
|
23
|
+
add_cookies(request) if options[:use_cookies]
|
24
|
+
request.basic_auth(@options[:username], @options[:password])
|
25
|
+
response = basic_auth_http_conn.request(request)
|
26
|
+
store_cookies(response) if options[:use_cookies]
|
27
|
+
response
|
28
|
+
end
|
29
|
+
|
30
|
+
def basic_auth_http_conn
|
31
|
+
http_conn(uri)
|
32
|
+
end
|
33
|
+
|
34
|
+
def http_conn(uri)
|
35
|
+
if @options[:proxy_address]
|
36
|
+
http_class = Net::HTTP::Proxy(@options[:proxy_address], @options[:proxy_port] ? @options[:proxy_port] : 80)
|
37
|
+
else
|
38
|
+
http_class = Net::HTTP
|
39
|
+
end
|
40
|
+
http_conn = http_class.new(uri.host, uri.port)
|
41
|
+
http_conn.use_ssl = @options[:use_ssl]
|
42
|
+
http_conn.verify_mode = @options[:ssl_verify_mode]
|
43
|
+
http_conn
|
44
|
+
end
|
45
|
+
|
46
|
+
def uri
|
47
|
+
uri = URI.parse(@options[:site])
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def store_cookies(response)
|
53
|
+
cookies = response.get_fields('set-cookie')
|
54
|
+
if cookies
|
55
|
+
cookies.each do |cookie|
|
56
|
+
data = CGI::Cookie.parse(cookie)
|
57
|
+
data.delete('Path')
|
58
|
+
@cookies.merge!(data)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def add_cookies(request)
|
64
|
+
cookie_array = @cookies.values.map { |cookie| cookie.to_s }
|
65
|
+
request.add_field('Cookie', cookie_array.join('; ')) if cookie_array.any?
|
66
|
+
request
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
module JIRA
|
3
|
+
|
4
|
+
class HTTPError < StandardError
|
5
|
+
extend Forwardable
|
6
|
+
|
7
|
+
def_instance_delegators :@response, :message, :code
|
8
|
+
attr_reader :response
|
9
|
+
|
10
|
+
def initialize(response)
|
11
|
+
@response = response
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'oauth'
|
2
|
+
require 'json'
|
3
|
+
require 'forwardable'
|
4
|
+
|
5
|
+
module JIRA
|
6
|
+
class OauthClient < RequestClient
|
7
|
+
|
8
|
+
DEFAULT_OPTIONS = {
|
9
|
+
:signature_method => 'RSA-SHA1',
|
10
|
+
:request_token_path => "/plugins/servlet/oauth/request-token",
|
11
|
+
:authorize_path => "/plugins/servlet/oauth/authorize",
|
12
|
+
:access_token_path => "/plugins/servlet/oauth/access-token",
|
13
|
+
:private_key_file => "rsakey.pem",
|
14
|
+
:consumer_key => nil,
|
15
|
+
:consumer_secret => nil
|
16
|
+
}
|
17
|
+
|
18
|
+
# This exception is thrown when the client is used before the OAuth access token
|
19
|
+
# has been initialized.
|
20
|
+
class UninitializedAccessTokenError < StandardError
|
21
|
+
def message
|
22
|
+
"init_access_token must be called before using the client"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
extend Forwardable
|
27
|
+
|
28
|
+
attr_accessor :consumer
|
29
|
+
attr_reader :options
|
30
|
+
|
31
|
+
def_instance_delegators :@consumer, :key, :secret, :get_request_token
|
32
|
+
|
33
|
+
def initialize(options)
|
34
|
+
@options = DEFAULT_OPTIONS.merge(options)
|
35
|
+
@consumer = init_oauth_consumer(@options)
|
36
|
+
end
|
37
|
+
|
38
|
+
def init_oauth_consumer(options)
|
39
|
+
@options[:request_token_path] = @options[:context_path] + @options[:request_token_path]
|
40
|
+
@options[:authorize_path] = @options[:context_path] + @options[:authorize_path]
|
41
|
+
@options[:access_token_path] = @options[:context_path] + @options[:access_token_path]
|
42
|
+
OAuth::Consumer.new(@options[:consumer_key],@options[:consumer_secret],@options)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Returns the current request token if it is set, else it creates
|
46
|
+
# and sets a new token.
|
47
|
+
def request_token
|
48
|
+
@request_token ||= get_request_token
|
49
|
+
end
|
50
|
+
|
51
|
+
# Sets the request token from a given token and secret.
|
52
|
+
def set_request_token(token, secret)
|
53
|
+
@request_token = OAuth::RequestToken.new(@consumer, token, secret)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Initialises and returns a new access token from the params hash
|
57
|
+
# returned by the OAuth transaction.
|
58
|
+
def init_access_token(params)
|
59
|
+
@access_token = request_token.get_access_token(params)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Sets the access token from a preexisting token and secret.
|
63
|
+
def set_access_token(token, secret)
|
64
|
+
@access_token = OAuth::AccessToken.new(@consumer, token, secret)
|
65
|
+
end
|
66
|
+
|
67
|
+
# Returns the current access token. Raises an
|
68
|
+
# JIRA::Client::UninitializedAccessTokenError exception if it is not set.
|
69
|
+
def access_token
|
70
|
+
raise UninitializedAccessTokenError.new unless @access_token
|
71
|
+
@access_token
|
72
|
+
end
|
73
|
+
|
74
|
+
def make_request(http_method, path, body='', headers={})
|
75
|
+
case http_method
|
76
|
+
when :delete, :get, :head
|
77
|
+
response = access_token.send http_method, path, headers
|
78
|
+
when :post, :put
|
79
|
+
response = access_token.send http_method, path, body, headers
|
80
|
+
end
|
81
|
+
response
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
data/lib/jira/railtie.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'oauth'
|
2
|
+
require 'json'
|
3
|
+
require 'net/https'
|
4
|
+
|
5
|
+
module JIRA
|
6
|
+
class RequestClient
|
7
|
+
|
8
|
+
# Returns the response if the request was successful (HTTP::2xx) and
|
9
|
+
# raises a JIRA::HTTPError if it was not successful, with the response
|
10
|
+
# attached.
|
11
|
+
|
12
|
+
def request(*args)
|
13
|
+
response = make_request(*args)
|
14
|
+
raise HTTPError.new(response) unless response.kind_of?(Net::HTTPSuccess)
|
15
|
+
response
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module JIRA
|
2
|
+
module Resource
|
3
|
+
class FilterFactory < JIRA::BaseFactory # :nodoc:
|
4
|
+
end
|
5
|
+
|
6
|
+
class Filter < JIRA::Base
|
7
|
+
has_one :owner, :class => JIRA::Resource::User
|
8
|
+
|
9
|
+
# Returns all the issues for this filter
|
10
|
+
def issues
|
11
|
+
Issue.jql(self.client, self.jql)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
|
3
|
+
module JIRA
|
4
|
+
module Resource
|
5
|
+
|
6
|
+
class IssueFactory < JIRA::BaseFactory # :nodoc:
|
7
|
+
end
|
8
|
+
|
9
|
+
class Issue < JIRA::Base
|
10
|
+
|
11
|
+
has_one :reporter, :class => JIRA::Resource::User,
|
12
|
+
:nested_under => 'fields'
|
13
|
+
has_one :assignee, :class => JIRA::Resource::User,
|
14
|
+
:nested_under => 'fields'
|
15
|
+
has_one :project, :nested_under => 'fields'
|
16
|
+
|
17
|
+
has_one :issuetype, :nested_under => 'fields'
|
18
|
+
|
19
|
+
has_one :priority, :nested_under => 'fields'
|
20
|
+
|
21
|
+
has_one :status, :nested_under => 'fields'
|
22
|
+
|
23
|
+
has_many :transitions
|
24
|
+
|
25
|
+
has_many :components, :nested_under => 'fields'
|
26
|
+
|
27
|
+
has_many :comments, :nested_under => ['fields','comment']
|
28
|
+
|
29
|
+
has_many :attachments, :nested_under => 'fields',
|
30
|
+
:attribute_key => 'attachment'
|
31
|
+
|
32
|
+
has_many :versions, :nested_under => 'fields'
|
33
|
+
|
34
|
+
has_many :worklogs, :nested_under => ['fields','worklog']
|
35
|
+
|
36
|
+
def self.all(client)
|
37
|
+
response = client.get(
|
38
|
+
client.options[:rest_base_path] + "/search",
|
39
|
+
:expand => 'transitions.fields'
|
40
|
+
)
|
41
|
+
json = parse_json(response.body)
|
42
|
+
json['issues'].map do |issue|
|
43
|
+
client.Issue.build(issue)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.jql(client, jql, fields = nil)
|
48
|
+
url = client.options[:rest_base_path] + "/search?jql=" + CGI.escape(jql)
|
49
|
+
url += CGI.escape("&fields=#{fields.join(",")}") if fields
|
50
|
+
response = client.get(url)
|
51
|
+
json = parse_json(response.body)
|
52
|
+
json['issues'].map do |issue|
|
53
|
+
client.Issue.build(issue)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def respond_to?(method_name)
|
58
|
+
if attrs.keys.include?('fields') && attrs['fields'].keys.include?(method_name.to_s)
|
59
|
+
true
|
60
|
+
else
|
61
|
+
super(method_name)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def method_missing(method_name, *args, &block)
|
66
|
+
if attrs.keys.include?('fields') && attrs['fields'].keys.include?(method_name.to_s)
|
67
|
+
attrs['fields'][method_name.to_s]
|
68
|
+
else
|
69
|
+
super(method_name)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module JIRA
|
2
|
+
module Resource
|
3
|
+
|
4
|
+
class ProjectFactory < JIRA::BaseFactory # :nodoc:
|
5
|
+
end
|
6
|
+
|
7
|
+
class Project < JIRA::Base
|
8
|
+
|
9
|
+
has_one :lead, :class => JIRA::Resource::User
|
10
|
+
has_many :components
|
11
|
+
has_many :issuetypes, :attribute_key => 'issueTypes'
|
12
|
+
has_many :versions
|
13
|
+
|
14
|
+
def self.key_attribute
|
15
|
+
:key
|
16
|
+
end
|
17
|
+
|
18
|
+
# Returns all the issues for this project
|
19
|
+
def issues(options={})
|
20
|
+
search_url = client.options[:rest_base_path] + '/search'
|
21
|
+
query_params = {:jql => "project=\"#{key}\""}
|
22
|
+
query_params.update Base.query_params_for_search(options)
|
23
|
+
response = client.get(url_with_query_params(search_url, query_params))
|
24
|
+
json = self.class.parse_json(response.body)
|
25
|
+
json['issues'].map do |issue|
|
26
|
+
client.Issue.build(issue)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module JIRA
|
2
|
+
module Resource
|
3
|
+
|
4
|
+
class TransitionFactory < JIRA::BaseFactory # :nodoc:
|
5
|
+
end
|
6
|
+
|
7
|
+
class Transition < JIRA::Base
|
8
|
+
has_one :to, :class => JIRA::Resource::Status
|
9
|
+
belongs_to :issue
|
10
|
+
|
11
|
+
nested_collections true
|
12
|
+
|
13
|
+
def self.endpoint_name
|
14
|
+
'transitions'
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.all(client, options = {})
|
18
|
+
issue = options[:issue]
|
19
|
+
unless issue
|
20
|
+
raise ArgumentError.new("parent issue is required")
|
21
|
+
end
|
22
|
+
|
23
|
+
path = "#{issue.self}/#{endpoint_name}?expand=transitions.fields"
|
24
|
+
response = client.get(path)
|
25
|
+
json = parse_json(response.body)
|
26
|
+
json['transitions'].map do |transition|
|
27
|
+
issue.transitions.build(transition)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module JIRA
|
2
|
+
module Resource
|
3
|
+
|
4
|
+
class UserFactory < JIRA::BaseFactory # :nodoc:
|
5
|
+
end
|
6
|
+
|
7
|
+
class User < JIRA::Base
|
8
|
+
def self.singular_path(client, key, prefix = '/')
|
9
|
+
collection_path(client, prefix) + '?username=' + key
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module JIRA
|
2
|
+
module Resource
|
3
|
+
|
4
|
+
class WorklogFactory < JIRA::BaseFactory # :nodoc:
|
5
|
+
end
|
6
|
+
|
7
|
+
class Worklog < JIRA::Base
|
8
|
+
has_one :author, :class => JIRA::Resource::User
|
9
|
+
has_one :update_author, :class => JIRA::Resource::User,
|
10
|
+
:attribute_key => "updateAuthor"
|
11
|
+
belongs_to :issue
|
12
|
+
nested_collections true
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
data/lib/jira/tasks.rb
ADDED
File without changes
|
data/lib/jira/version.rb
ADDED
data/lib/jira.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
$: << File.expand_path(File.dirname(__FILE__))
|
2
|
+
|
3
|
+
require 'active_support/inflector'
|
4
|
+
ActiveSupport::Inflector.inflections do |inflector|
|
5
|
+
inflector.singular 'status', 'status'
|
6
|
+
end
|
7
|
+
|
8
|
+
require 'jira/base'
|
9
|
+
require 'jira/base_factory'
|
10
|
+
require 'jira/has_many_proxy'
|
11
|
+
require 'jira/http_error'
|
12
|
+
|
13
|
+
require 'jira/resource/user'
|
14
|
+
require 'jira/resource/attachment'
|
15
|
+
require 'jira/resource/component'
|
16
|
+
require 'jira/resource/issuetype'
|
17
|
+
require 'jira/resource/version'
|
18
|
+
require 'jira/resource/status'
|
19
|
+
require 'jira/resource/transition'
|
20
|
+
require 'jira/resource/project'
|
21
|
+
require 'jira/resource/priority'
|
22
|
+
require 'jira/resource/comment'
|
23
|
+
require 'jira/resource/worklog'
|
24
|
+
require 'jira/resource/issue'
|
25
|
+
require 'jira/resource/filter'
|
26
|
+
require 'jira/resource/field'
|
27
|
+
|
28
|
+
require 'jira/request_client'
|
29
|
+
require 'jira/oauth_client'
|
30
|
+
require 'jira/http_client'
|
31
|
+
require 'jira/client'
|
32
|
+
|
33
|
+
require 'jira/railtie' if defined?(Rails)
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
|
3
|
+
namespace :jira do
|
4
|
+
desc "Generate a consumer key for your application"
|
5
|
+
task :generate_consumer_key do
|
6
|
+
key = SecureRandom.hex(16)
|
7
|
+
puts "You can use this as your consumer key: #{key}"
|
8
|
+
end
|
9
|
+
|
10
|
+
desc "Run the system call to generate a RSA public certificate"
|
11
|
+
task :generate_public_cert do
|
12
|
+
puts "Executing 'openssl req -x509 -nodes -newkey rsa:1024 -sha1 -keyout rsakey.pem -out rsacert.pem'"
|
13
|
+
system('openssl req -x509 -subj "/C=US/ST=New York/L=New York/O=SUMO Heavy Industries/CN=www.sumoheavy.com" -nodes -newkey rsa:1024 -sha1 -keyout rsakey.pem -out rsacert.pem')
|
14
|
+
puts "Done. The RSA-SHA1 private keyfile is in the current directory: \'rsakey.pem\'."
|
15
|
+
puts "You will need to copy the following certificate into your application link configuration in Jira:"
|
16
|
+
system("cat rsacert.pem")
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe JIRA::Resource::Attachment do
|
4
|
+
|
5
|
+
with_each_client do |site_url, client|
|
6
|
+
let(:client) { client }
|
7
|
+
let(:site_url) { site_url }
|
8
|
+
|
9
|
+
let(:key) { "10000" }
|
10
|
+
|
11
|
+
let(:expected_attributes) do
|
12
|
+
{
|
13
|
+
'self' => "http://localhost:2990/jira/rest/api/2/attachment/10000",
|
14
|
+
'size' => 15360,
|
15
|
+
'filename' => "ballmer.png"
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
it_should_behave_like "a resource"
|
20
|
+
it_should_behave_like "a resource with a singular GET endpoint"
|
21
|
+
it_should_behave_like "a resource with a DELETE endpoint"
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe JIRA::Resource::Comment do
|
4
|
+
|
5
|
+
with_each_client do |site_url, client|
|
6
|
+
let(:client) { client }
|
7
|
+
let(:site_url) { site_url }
|
8
|
+
|
9
|
+
let(:key) { "10000" }
|
10
|
+
|
11
|
+
let(:target) { JIRA::Resource::Comment.new(client, :attrs => {'id' => '99999'}, :issue_id => '54321') }
|
12
|
+
|
13
|
+
let(:expected_collection_length) { 2 }
|
14
|
+
|
15
|
+
let(:belongs_to) {
|
16
|
+
JIRA::Resource::Issue.new(client, :attrs => {
|
17
|
+
'id' => '10002',
|
18
|
+
'fields' => {
|
19
|
+
'comment' => {'comments' => []}
|
20
|
+
}
|
21
|
+
})
|
22
|
+
}
|
23
|
+
|
24
|
+
let(:expected_attributes) do
|
25
|
+
{
|
26
|
+
'self' => "http://localhost:2990/jira/rest/api/2/issue/10002/comment/10000",
|
27
|
+
'id' => key,
|
28
|
+
'body' => "This is a comment. Creative."
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
let(:attributes_for_post) {
|
33
|
+
{ "body" => "new comment" }
|
34
|
+
}
|
35
|
+
let(:expected_attributes_from_post) {
|
36
|
+
{ "id" => "10001", "body" => "new comment"}
|
37
|
+
}
|
38
|
+
|
39
|
+
let(:attributes_for_put) {
|
40
|
+
{"body" => "new body"}
|
41
|
+
}
|
42
|
+
let(:expected_attributes_from_put) {
|
43
|
+
{ "id" => "10000", "body" => "new body" }
|
44
|
+
}
|
45
|
+
|
46
|
+
it_should_behave_like "a resource"
|
47
|
+
it_should_behave_like "a resource with a collection GET endpoint"
|
48
|
+
it_should_behave_like "a resource with a singular GET endpoint"
|
49
|
+
it_should_behave_like "a resource with a DELETE endpoint"
|
50
|
+
it_should_behave_like "a resource with a POST endpoint"
|
51
|
+
it_should_behave_like "a resource with a PUT endpoint"
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|