sclemmer-jira-ruby 0.1.12
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/lib/jira.rb +33 -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 +80 -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/tasks/generate.rake +18 -0
- data/sclemmer-jira-ruby.gemspec +28 -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 +583 -0
- data/spec/jira/client_spec.rb +188 -0
- data/spec/jira/has_many_proxy_spec.rb +47 -0
- data/spec/jira/http_client_spec.rb +109 -0
- data/spec/jira/http_error_spec.rb +26 -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 +123 -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.post.json +28 -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/field.json +32 -0
- data/spec/mock_responses/field/1.json +15 -0
- data/spec/mock_responses/issue.json +1108 -0
- data/spec/mock_responses/issue.post.json +5 -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/10002/comment.json +65 -0
- data/spec/mock_responses/issue/10002/comment.post.json +29 -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/transitions.json +49 -0
- data/spec/mock_responses/issue/10002/transitions.post.json +1 -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/worklog/10000.json +31 -0
- data/spec/mock_responses/issue/10002/worklog/10000.put.json +30 -0
- data/spec/mock_responses/issuetype.json +42 -0
- data/spec/mock_responses/issuetype/5.json +8 -0
- data/spec/mock_responses/priority.json +42 -0
- data/spec/mock_responses/priority/1.json +8 -0
- data/spec/mock_responses/project.json +12 -0
- data/spec/mock_responses/project/SAMPLEPROJECT.issues.json +1108 -0
- data/spec/mock_responses/project/SAMPLEPROJECT.json +84 -0
- data/spec/mock_responses/status.json +37 -0
- data/spec/mock_responses/status/1.json +7 -0
- data/spec/mock_responses/user_username=admin.json +17 -0
- data/spec/mock_responses/version.post.json +7 -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/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 +194 -0
- metadata +302 -0
@@ -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,80 @@
|
|
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, options = {fields: nil, start_at: nil, max_results: nil})
|
48
|
+
url = client.options[:rest_base_path] + "/search?jql=" + CGI.escape(jql)
|
49
|
+
|
50
|
+
url << "&fields=#{options[:fields].map{ |value| CGI.escape(value.to_s) }.join(',')}" if options[:fields]
|
51
|
+
url << "&startAt=#{CGI.escape(options[:start_at].to_s)}" if options[:start_at]
|
52
|
+
url << "&maxResults=#{CGI.escape(options[:max_results].to_s)}" if options[:max_results]
|
53
|
+
|
54
|
+
response = client.get(url)
|
55
|
+
json = parse_json(response.body)
|
56
|
+
json['issues'].map do |issue|
|
57
|
+
client.Issue.build(issue)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def respond_to?(method_name)
|
62
|
+
if attrs.keys.include?('fields') && attrs['fields'].keys.include?(method_name.to_s)
|
63
|
+
true
|
64
|
+
else
|
65
|
+
super(method_name)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def method_missing(method_name, *args, &block)
|
70
|
+
if attrs.keys.include?('fields') && attrs['fields'].keys.include?(method_name.to_s)
|
71
|
+
attrs['fields'][method_name.to_s]
|
72
|
+
else
|
73
|
+
super(method_name)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
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
@@ -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,28 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "jira/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "sclemmer-jira-ruby"
|
7
|
+
s.version = JIRA::VERSION
|
8
|
+
s.authors = ["SUMO Heavy Industries"]
|
9
|
+
s.homepage = "http://www.sumoheavy.com"
|
10
|
+
s.summary = %q{Ruby Gem for use with the Atlassian JIRA REST API}
|
11
|
+
s.description = %q{API for JIRA}
|
12
|
+
s.licenses = ["OSL-3.0"]
|
13
|
+
|
14
|
+
s.rubyforge_project = "jira-ruby"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
s.add_development_dependency "railties", '~> 4.1.4'
|
22
|
+
s.add_runtime_dependency "oauth", '~> 0.4.7'
|
23
|
+
s.add_runtime_dependency "activesupport", '~> 4.1.4'
|
24
|
+
s.add_development_dependency "webmock", '~> 1.18.0'
|
25
|
+
s.add_development_dependency "rspec", '~> 3.0.0'
|
26
|
+
s.add_development_dependency "rake", '~> 10.3.2'
|
27
|
+
end
|
28
|
+
|
@@ -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
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe JIRA::Resource::Component do
|
4
|
+
|
5
|
+
|
6
|
+
with_each_client do |site_url, client|
|
7
|
+
let(:client) { client }
|
8
|
+
let(:site_url) { site_url }
|
9
|
+
|
10
|
+
let(:key) { "10000" }
|
11
|
+
|
12
|
+
let(:expected_attributes) do
|
13
|
+
{
|
14
|
+
'self' => "http://localhost:2990/jira/rest/api/2/component/10000",
|
15
|
+
'id' => key,
|
16
|
+
'name' => "Cheesecake"
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
let(:attributes_for_post) {
|
21
|
+
{"name" => "Test component", "project" => "SAMPLEPROJECT" }
|
22
|
+
}
|
23
|
+
let(:expected_attributes_from_post) {
|
24
|
+
{ "id" => "10001", "name" => "Test component" }
|
25
|
+
}
|
26
|
+
|
27
|
+
let(:attributes_for_put) {
|
28
|
+
{"name" => "Jammy", "project" => "SAMPLEPROJECT" }
|
29
|
+
}
|
30
|
+
let(:expected_attributes_from_put) {
|
31
|
+
{ "id" => "10000", "name" => "Jammy" }
|
32
|
+
}
|
33
|
+
|
34
|
+
it_should_behave_like "a resource"
|
35
|
+
it_should_behave_like "a resource with a singular GET endpoint"
|
36
|
+
it_should_behave_like "a resource with a DELETE endpoint"
|
37
|
+
it_should_behave_like "a resource with a POST endpoint"
|
38
|
+
it_should_behave_like "a resource with a PUT endpoint"
|
39
|
+
it_should_behave_like "a resource with a PUT endpoint that rejects invalid fields"
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|