embulk-input-jira 0.0.4 → 0.0.5
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 +8 -0
- data/Gemfile +1 -1
- data/README.md +2 -0
- data/Rakefile +5 -6
- data/embulk-input-jira.gemspec +1 -3
- data/lib/embulk/input/jira.rb +137 -3
- data/lib/embulk/input/jira_api.rb +9 -0
- data/lib/embulk/input/{jira/api.rb → jira_api/client.rb} +4 -4
- data/lib/embulk/input/{jira → jira_api}/issue.rb +1 -1
- data/spec/embulk/input/{jira/api_spec.rb → jira_api/client_spec.rb} +11 -11
- data/spec/embulk/input/{jira → jira_api}/issue_spec.rb +7 -7
- data/spec/embulk/input/{jira_input_plugin_spec.rb → jira_spec.rb} +82 -28
- data/spec/embulk_spec.rb +2 -2
- data/spec/support/stdout_and_err_capture.rb +19 -6
- metadata +11 -12
- data/lib/embulk/input/jira/version.rb +0 -7
- data/lib/embulk/input/jira_input_plugin.rb +0 -135
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 14d965de93b1ed1a36384160c678009c61e87f12
|
4
|
+
data.tar.gz: cc230ada4b25382dc40ce20912f9e87181e8ca72
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 207f74f545d0d951ef5f8644f3557d3a60d6e1599e184eb88a6bcc6d491e38c55482350c6301e73651c8faf08dc572ad53f82dc82e53ada8fe683472fb81e491
|
7
|
+
data.tar.gz: 9cd3d4d3b4ac8909945d6de6e67b24c309ddcf00a457410d9abc6f564bdacbf7153947fc79fd4f341808faa5876d25de6a1d745c4d7e57e2e34b6f4c9f3f0ed2
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
## 0.0.5 - 2015-06-24
|
2
|
+
|
3
|
+
**Embulk 0.6.12+ is required since this version**
|
4
|
+
|
5
|
+
* [enhancement] Follow embulk 0.6.12 [#29](https://github.com/treasure-data/embulk-input-jira/pull/29)
|
6
|
+
* [maintenance] Separate preview method [#32](https://github.com/treasure-data/embulk-input-jira/pull/32)
|
7
|
+
* [maintenance] Restructure files [#30](https://github.com/treasure-data/embulk-input-jira/pull/30)
|
8
|
+
|
1
9
|
## 0.0.4 - 2015-06-22
|
2
10
|
* [enhancement] Add more schema generated by guess command [#27](https://github.com/treasure-data/embulk-input-jira/pull/27)
|
3
11
|
|
data/Gemfile
CHANGED
@@ -2,7 +2,7 @@ source 'https://rubygems.org/'
|
|
2
2
|
|
3
3
|
# NOTE: Bundler.require(:runtime, :development) in spec_helper that require all dependencies
|
4
4
|
# but require 'embulk' will be failed. so separate it from gemspec ecosystem
|
5
|
-
gem 'embulk', ">= 0.6", "< 1.0"
|
5
|
+
gem 'embulk', ">= 0.6.12", "< 1.0"
|
6
6
|
gem "codeclimate-test-reporter", require: nil
|
7
7
|
|
8
8
|
gemspec
|
data/README.md
CHANGED
data/Rakefile
CHANGED
@@ -3,7 +3,6 @@ require 'rspec/core/rake_task'
|
|
3
3
|
require "json"
|
4
4
|
require "pathname"
|
5
5
|
require "open-uri"
|
6
|
-
require File.expand_path("../lib/embulk/input/jira/version.rb", __FILE__)
|
7
6
|
|
8
7
|
|
9
8
|
task default: :spec
|
@@ -18,11 +17,12 @@ namespace :release do
|
|
18
17
|
task :prepare do
|
19
18
|
root_dir = Pathname.new(File.expand_path("../", __FILE__))
|
20
19
|
changelog_file = root_dir.join("CHANGELOG.md")
|
20
|
+
gemspec_file = root_dir.join("embulk-input-jira.gemspec")
|
21
21
|
|
22
22
|
system("git fetch origin")
|
23
23
|
|
24
24
|
# detect merged PR
|
25
|
-
old_version =
|
25
|
+
old_version = gemspec_file.read[/spec\.version += *"([0-9]+\.[0-9]+\.[0-9]+)"/, 1]
|
26
26
|
pr_numbers = `git log v#{old_version}..origin/master --oneline`.scan(/#[0-9]+/)
|
27
27
|
|
28
28
|
if !$?.success? || pr_numbers.empty?
|
@@ -51,10 +51,9 @@ HEADER
|
|
51
51
|
File.open(changelog_file, "w") {|f| f.write(new_changelog) }
|
52
52
|
|
53
53
|
# Update version.rb
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
f.write old_content.gsub(old_version, new_version)
|
54
|
+
old_content = gemspec_file.read
|
55
|
+
File.open(gemspec_file, "w") do |f|
|
56
|
+
f.write old_content.gsub(/(spec\.version += *)".*?"/, %Q!\\1"#{new_version}"!)
|
58
57
|
end
|
59
58
|
|
60
59
|
# Update Gemfile.lock
|
data/embulk-input-jira.gemspec
CHANGED
@@ -1,8 +1,6 @@
|
|
1
|
-
require File.expand_path("../lib/embulk/input/jira/version.rb", __FILE__)
|
2
|
-
|
3
1
|
Gem::Specification.new do |spec|
|
4
2
|
spec.name = "embulk-input-jira"
|
5
|
-
spec.version =
|
3
|
+
spec.version = "0.0.5"
|
6
4
|
spec.authors = ["uu59", "yoshihara"]
|
7
5
|
spec.summary = "Jira input plugin for Embulk"
|
8
6
|
spec.description = "Loads records from Jira."
|
data/lib/embulk/input/jira.rb
CHANGED
@@ -1,9 +1,143 @@
|
|
1
|
-
require "embulk/input/
|
2
|
-
require "embulk/input/
|
1
|
+
require "embulk/input/jira_input_plugin_utils"
|
2
|
+
require "embulk/input/jira_api"
|
3
3
|
|
4
4
|
module Embulk
|
5
5
|
module Input
|
6
|
-
|
6
|
+
class Jira < InputPlugin
|
7
|
+
PER_PAGE = 50
|
8
|
+
GUESS_RECORDS_COUNT = 10
|
9
|
+
PREVIEW_RECORDS_COUNT = 15
|
10
|
+
|
11
|
+
Plugin.register_input("jira", self)
|
12
|
+
|
13
|
+
def self.transaction(config, &control)
|
14
|
+
task = {
|
15
|
+
"username" => config.param("username", :string),
|
16
|
+
"password" => config.param("password", :string),
|
17
|
+
"uri" => config.param("uri", :string),
|
18
|
+
"jql" => config.param("jql", :string),
|
19
|
+
}
|
20
|
+
|
21
|
+
attributes = {}
|
22
|
+
columns = config.param("columns", :array).map do |column|
|
23
|
+
name = column["name"]
|
24
|
+
type = column["type"].to_sym
|
25
|
+
attributes[name] = type
|
26
|
+
Column.new(nil, name, type, column["format"])
|
27
|
+
end
|
28
|
+
|
29
|
+
task["attributes"] = attributes
|
30
|
+
|
31
|
+
resume(task, columns, 1, &control)
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.resume(task, columns, count, &control)
|
35
|
+
commit_reports = yield(task, columns, count)
|
36
|
+
|
37
|
+
next_config_diff = {}
|
38
|
+
return next_config_diff
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.guess(config)
|
42
|
+
# TODO: api_version should be 2 (the latest version)
|
43
|
+
# auth_type should be specified from config. (The future task)
|
44
|
+
|
45
|
+
username = config.param("username", :string)
|
46
|
+
password = config.param("password", :string)
|
47
|
+
uri = config.param("uri", :string)
|
48
|
+
api_version = "latest"
|
49
|
+
auth_type = "basic"
|
50
|
+
jql = config.param("jql", :string)
|
51
|
+
|
52
|
+
jira = JiraApi::Client.setup do |jira_config|
|
53
|
+
jira_config.username = username
|
54
|
+
jira_config.password = password
|
55
|
+
jira_config.uri = uri
|
56
|
+
jira_config.api_version = api_version
|
57
|
+
jira_config.auth_type = auth_type
|
58
|
+
end
|
59
|
+
|
60
|
+
# TODO: we use 0..10 issues to guess config?
|
61
|
+
records = jira.search_issues(jql, max_results: GUESS_RECORDS_COUNT).map do |issue|
|
62
|
+
issue.to_record
|
63
|
+
end
|
64
|
+
|
65
|
+
columns = JiraInputPluginUtils.guess_columns(records)
|
66
|
+
|
67
|
+
guessed_config = {
|
68
|
+
"columns" => columns,
|
69
|
+
}
|
70
|
+
|
71
|
+
return guessed_config
|
72
|
+
end
|
73
|
+
|
74
|
+
def init
|
75
|
+
@attributes = task["attributes"]
|
76
|
+
@jira = JiraApi::Client.setup do |config|
|
77
|
+
config.username = task["username"]
|
78
|
+
config.password = task["password"]
|
79
|
+
config.uri = task["uri"]
|
80
|
+
config.api_version = "latest"
|
81
|
+
config.auth_type = :basic
|
82
|
+
end
|
83
|
+
@jql = task["jql"]
|
84
|
+
end
|
85
|
+
|
86
|
+
def run
|
87
|
+
return preview if preview?
|
88
|
+
options = {}
|
89
|
+
total_count = @jira.total_count(@jql)
|
90
|
+
last_page = (total_count.to_f / PER_PAGE).ceil
|
91
|
+
|
92
|
+
0.step(total_count, PER_PAGE).with_index(1) do |start_at, page|
|
93
|
+
logger.debug "Fetching #{page} / #{last_page} page"
|
94
|
+
@jira.search_issues(@jql, options.merge(start_at: start_at)).each do |issue|
|
95
|
+
values = @attributes.map do |(attribute_name, type)|
|
96
|
+
JiraInputPluginUtils.cast(issue[attribute_name], type)
|
97
|
+
end
|
98
|
+
|
99
|
+
page_builder.add(values)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
page_builder.finish
|
104
|
+
|
105
|
+
commit_report = {}
|
106
|
+
return commit_report
|
107
|
+
end
|
108
|
+
|
109
|
+
def self.logger
|
110
|
+
Embulk.logger
|
111
|
+
end
|
112
|
+
|
113
|
+
def logger
|
114
|
+
self.class.logger
|
115
|
+
end
|
116
|
+
|
117
|
+
private
|
118
|
+
|
119
|
+
def preview
|
120
|
+
logger.debug "For preview mode, JIRA input plugin fetches records at most #{PREVIEW_RECORDS_COUNT}"
|
121
|
+
@jira.search_issues(@jql, max_results: PREVIEW_RECORDS_COUNT).each do |issue|
|
122
|
+
values = @attributes.map do |(attribute_name, type)|
|
123
|
+
JiraInputPluginUtils.cast(issue[attribute_name], type)
|
124
|
+
end
|
125
|
+
page_builder.add(values)
|
126
|
+
end
|
127
|
+
page_builder.finish
|
128
|
+
|
129
|
+
commit_report = {}
|
130
|
+
return commit_report
|
131
|
+
end
|
132
|
+
|
133
|
+
def preview?
|
134
|
+
begin
|
135
|
+
# http://www.embulk.org/docs/release/release-0.6.12.html
|
136
|
+
org.embulk.spi.Exec.isPreview()
|
137
|
+
rescue java.lang.NullPointerException => e
|
138
|
+
false
|
139
|
+
end
|
140
|
+
end
|
7
141
|
end
|
8
142
|
end
|
9
143
|
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
require "jiralicious"
|
2
|
-
require "embulk/input/
|
2
|
+
require "embulk/input/jira_api/issue"
|
3
3
|
require "timeout"
|
4
4
|
|
5
5
|
module Embulk
|
6
6
|
module Input
|
7
|
-
module
|
8
|
-
class
|
7
|
+
module JiraApi
|
8
|
+
class Client
|
9
9
|
SEARCH_TIMEOUT_SECONDS = 5
|
10
10
|
SEARCH_ISSUES_TIMEOUT_SECONDS = 60
|
11
11
|
DEFAULT_SEARCH_RETRY_TIMES = 10
|
@@ -18,7 +18,7 @@ module Embulk
|
|
18
18
|
def search_issues(jql, options={})
|
19
19
|
timeout_and_retry(SEARCH_ISSUES_TIMEOUT_SECONDS) do
|
20
20
|
search(jql, options).issues.map do |issue|
|
21
|
-
|
21
|
+
JiraApi::Issue.new(issue)
|
22
22
|
end
|
23
23
|
end
|
24
24
|
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
|
-
describe Embulk::Input::
|
3
|
+
describe Embulk::Input::JiraApi::Client do
|
4
4
|
describe ".setup" do
|
5
|
-
subject { Embulk::Input::
|
5
|
+
subject { Embulk::Input::JiraApi::Client.setup {} }
|
6
6
|
|
7
|
-
it "returns Embulk::Input::
|
8
|
-
expect(subject.is_a?(Embulk::Input::
|
7
|
+
it "returns Embulk::Input::JiraApi::Client instance" do
|
8
|
+
expect(subject.is_a?(Embulk::Input::JiraApi::Client)).to be_truthy
|
9
9
|
end
|
10
10
|
|
11
11
|
it "calls Jiralicious.configure" do
|
@@ -15,7 +15,7 @@ describe Embulk::Input::Jira::Api do
|
|
15
15
|
|
16
16
|
describe "#search" do
|
17
17
|
let(:jql) { "project=FOO" }
|
18
|
-
let(:api) { Embulk::Input::
|
18
|
+
let(:api) { Embulk::Input::JiraApi::Client.new }
|
19
19
|
|
20
20
|
subject { api.search(jql) }
|
21
21
|
|
@@ -30,7 +30,7 @@ describe Embulk::Input::Jira::Api do
|
|
30
30
|
end
|
31
31
|
|
32
32
|
it "retry DEFAULT_SEARCH_RETRY_TIMES times then raise error" do
|
33
|
-
expect(Timeout).to receive(:timeout).exactly(Embulk::Input::
|
33
|
+
expect(Timeout).to receive(:timeout).exactly(Embulk::Input::JiraApi::Client::DEFAULT_SEARCH_RETRY_TIMES)
|
34
34
|
expect { subject }.to raise_error
|
35
35
|
end
|
36
36
|
end
|
@@ -67,20 +67,20 @@ describe Embulk::Input::Jira::Api do
|
|
67
67
|
]
|
68
68
|
end
|
69
69
|
|
70
|
-
subject { Embulk::Input::
|
70
|
+
subject { Embulk::Input::JiraApi::Client.new.search_issues(jql) }
|
71
71
|
|
72
72
|
it do
|
73
73
|
allow(Jiralicious).to receive_message_chain(:search, :issues).and_return(results)
|
74
74
|
|
75
75
|
expect(subject).to be_kind_of Array
|
76
|
-
expect(subject.map(&:class)).to match_array [Embulk::Input::
|
76
|
+
expect(subject.map(&:class)).to match_array [Embulk::Input::JiraApi::Issue, Embulk::Input::JiraApi::Issue]
|
77
77
|
end
|
78
78
|
end
|
79
79
|
|
80
80
|
describe "#total_count" do
|
81
81
|
subject { jira_api.total_count(jql) }
|
82
82
|
|
83
|
-
let(:jira_api) { Embulk::Input::
|
83
|
+
let(:jira_api) { Embulk::Input::JiraApi::Client.new }
|
84
84
|
let(:jql) { "project=FOO" }
|
85
85
|
let(:results) { Object.new } # add mock later
|
86
86
|
let(:results_count) { 5 }
|
@@ -89,7 +89,7 @@ describe Embulk::Input::Jira::Api do
|
|
89
89
|
allow(results).to receive(:num_results).and_return(results_count)
|
90
90
|
end
|
91
91
|
|
92
|
-
it "calls Embulk::Input::
|
92
|
+
it "calls Embulk::Input::JiraApi::Client#search with proper arguments" do
|
93
93
|
expect(jira_api).to receive(:search).with(jql, max_results: 1).and_return(results)
|
94
94
|
subject
|
95
95
|
end
|
@@ -103,7 +103,7 @@ describe Embulk::Input::Jira::Api do
|
|
103
103
|
describe "#timeout_and_retry" do
|
104
104
|
let(:wait) { 1 }
|
105
105
|
let(:retry_times) { 3 }
|
106
|
-
let(:jira_api) { Embulk::Input::
|
106
|
+
let(:jira_api) { Embulk::Input::JiraApi::Client.new }
|
107
107
|
let(:block) { proc{ "it works" } }
|
108
108
|
|
109
109
|
subject { jira_api.send(:timeout_and_retry, wait, retry_times, &block) }
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
|
-
describe Embulk::Input::
|
3
|
+
describe Embulk::Input::JiraApi::Issue do
|
4
4
|
describe ".initialize" do
|
5
5
|
context "when argument has 'fields' key" do
|
6
6
|
let(:issue_attributes) do
|
@@ -19,15 +19,15 @@ describe Embulk::Input::Jira::Issue do
|
|
19
19
|
end
|
20
20
|
|
21
21
|
it "has @id with argument['id']" do
|
22
|
-
expect(Embulk::Input::
|
22
|
+
expect(Embulk::Input::JiraApi::Issue.new(issue_attributes).id).to eq issue_attributes["id"]
|
23
23
|
end
|
24
24
|
|
25
25
|
it "has @key with argument['jira_key']" do
|
26
|
-
expect(Embulk::Input::
|
26
|
+
expect(Embulk::Input::JiraApi::Issue.new(issue_attributes).key).to eq issue_attributes["jira_key"]
|
27
27
|
end
|
28
28
|
|
29
29
|
it "has @fields with argument['fields']" do
|
30
|
-
expect(Embulk::Input::
|
30
|
+
expect(Embulk::Input::JiraApi::Issue.new(issue_attributes).fields).to eq issue_attributes["fields"]
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
@@ -37,13 +37,13 @@ describe Embulk::Input::Jira::Issue do
|
|
37
37
|
end
|
38
38
|
|
39
39
|
it "raises error" do
|
40
|
-
expect { Embulk::Input::
|
40
|
+
expect { Embulk::Input::JiraApi::Issue.new(issue_attributes) }.to raise_error
|
41
41
|
end
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
45
|
describe "#[]" do
|
46
|
-
subject { Embulk::Input::
|
46
|
+
subject { Embulk::Input::JiraApi::Issue.new(issue_attributes)[attribute_name] }
|
47
47
|
|
48
48
|
let(:issue_attributes) do
|
49
49
|
{
|
@@ -188,7 +188,7 @@ describe Embulk::Input::Jira::Issue do
|
|
188
188
|
|
189
189
|
describe "#to_record" do
|
190
190
|
subject do
|
191
|
-
Embulk::Input::
|
191
|
+
Embulk::Input::JiraApi::Issue.new(issue_attributes).to_record
|
192
192
|
end
|
193
193
|
|
194
194
|
shared_examples 'return guessed record' do
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
|
-
describe Embulk::Input::
|
3
|
+
describe Embulk::Input::Jira do
|
4
4
|
let(:username) { "jira-user" }
|
5
5
|
let(:password) { "password" }
|
6
6
|
let(:uri) { "http://jira.example/" }
|
@@ -8,7 +8,7 @@ describe Embulk::Input::JiraInputPlugin do
|
|
8
8
|
let(:project_name) { "FOO" }
|
9
9
|
|
10
10
|
describe ".transaction" do
|
11
|
-
subject {
|
11
|
+
subject { described_class.transaction(config, &control) }
|
12
12
|
|
13
13
|
let(:config) { Object.new } # add mock later
|
14
14
|
let(:control) { Proc.new{|task, columns, count| } } # do nothing
|
@@ -50,13 +50,13 @@ describe Embulk::Input::JiraInputPlugin do
|
|
50
50
|
|
51
51
|
# NOTE: I should check other factor, but i don't know it...
|
52
52
|
it "calls .resume method with proper parameters" do
|
53
|
-
expect(
|
53
|
+
expect(described_class).to receive(:resume).with(task, column_structs, 1, &control)
|
54
54
|
subject
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
58
58
|
describe ".resume" do
|
59
|
-
subject {
|
59
|
+
subject { described_class.resume(task, columns, count, &control) }
|
60
60
|
|
61
61
|
let(:task) do
|
62
62
|
{
|
@@ -89,12 +89,12 @@ describe Embulk::Input::JiraInputPlugin do
|
|
89
89
|
end
|
90
90
|
|
91
91
|
describe ".guess" do
|
92
|
-
subject {
|
92
|
+
subject { described_class.guess(config) }
|
93
93
|
|
94
94
|
let(:config) { Object.new } # add mock later
|
95
95
|
|
96
|
-
let(:jira_api) { Embulk::Input::
|
97
|
-
let(:jira_issues) { [Embulk::Input::
|
96
|
+
let(:jira_api) { Embulk::Input::JiraApi::Client.new }
|
97
|
+
let(:jira_issues) { [Embulk::Input::JiraApi::Issue.new(attributes)] }
|
98
98
|
let(:attributes) do
|
99
99
|
{
|
100
100
|
"id" => "100",
|
@@ -127,7 +127,7 @@ describe Embulk::Input::JiraInputPlugin do
|
|
127
127
|
end
|
128
128
|
|
129
129
|
before do
|
130
|
-
allow(jira_api).to receive(:search_issues).with(jql, max_results:
|
130
|
+
allow(jira_api).to receive(:search_issues).with(jql, max_results: described_class::GUESS_RECORDS_COUNT).and_return(jira_issues)
|
131
131
|
|
132
132
|
allow(config).to receive(:param).with("username", :string).and_return(username)
|
133
133
|
allow(config).to receive(:param).with("password", :string).and_return(password)
|
@@ -135,13 +135,13 @@ describe Embulk::Input::JiraInputPlugin do
|
|
135
135
|
allow(config).to receive(:param).with("jql", :string).and_return(jql)
|
136
136
|
end
|
137
137
|
|
138
|
-
it "setup Embulk::Input::
|
139
|
-
expect(Embulk::Input::
|
138
|
+
it "setup Embulk::Input::JiraApi::Client" do
|
139
|
+
expect(Embulk::Input::JiraApi::Client).to receive(:setup).and_return(jira_api)
|
140
140
|
subject
|
141
141
|
end
|
142
142
|
|
143
143
|
it "returns guessed config" do
|
144
|
-
allow(Embulk::Input::
|
144
|
+
allow(Embulk::Input::JiraApi::Client).to receive(:setup).and_return(jira_api)
|
145
145
|
|
146
146
|
expect(subject).to eq guessed_config
|
147
147
|
end
|
@@ -150,39 +150,39 @@ describe Embulk::Input::JiraInputPlugin do
|
|
150
150
|
describe "#init (.new)" do
|
151
151
|
# NOTE: InputPlugin.initialize calls #init method.
|
152
152
|
|
153
|
-
subject {
|
153
|
+
subject { described_class.new({}, nil, nil, nil) }
|
154
154
|
|
155
|
-
it "setup Embulk::Input::
|
156
|
-
expect(Embulk::Input::
|
155
|
+
it "setup Embulk::Input::JiraApi::Client" do
|
156
|
+
expect(Embulk::Input::JiraApi::Client).to receive(:setup)
|
157
157
|
subject
|
158
158
|
end
|
159
159
|
|
160
160
|
it "is a Embulk::InputPlugin" do
|
161
|
-
allow(Embulk::Input::
|
161
|
+
allow(Embulk::Input::JiraApi::Client).to receive(:setup)
|
162
162
|
expect(subject).to be_a(Embulk::InputPlugin)
|
163
163
|
end
|
164
164
|
end
|
165
165
|
|
166
166
|
describe "#run" do
|
167
167
|
subject do
|
168
|
-
|
169
|
-
|
170
|
-
|
168
|
+
allow(plugin).to receive(:logger).and_return(::Logger.new(File::NULL))
|
169
|
+
silence do
|
170
|
+
plugin.run
|
171
171
|
end
|
172
|
-
result
|
173
172
|
end
|
174
173
|
|
175
|
-
let(:
|
174
|
+
let(:plugin) { described_class.new(task, nil, nil, page_builder) }
|
175
|
+
let(:jira_api) { Embulk::Input::JiraApi::Client.new }
|
176
176
|
let(:jira_issues) do
|
177
177
|
(1..total_count).map do |i|
|
178
178
|
attributes = fields.merge("id" => i.to_s, "jira_key" => "FOO-#{i}")
|
179
179
|
|
180
|
-
Embulk::Input::
|
180
|
+
Embulk::Input::JiraApi::Issue.new(attributes)
|
181
181
|
end
|
182
182
|
end
|
183
183
|
|
184
184
|
let(:total_count) { max_result + 10 }
|
185
|
-
let(:max_result) {
|
185
|
+
let(:max_result) { described_class::PER_PAGE }
|
186
186
|
|
187
187
|
|
188
188
|
let(:page_builder) { Object.new } # add mock later
|
@@ -207,10 +207,10 @@ describe Embulk::Input::JiraInputPlugin do
|
|
207
207
|
let(:commit_report) { {} }
|
208
208
|
|
209
209
|
before do
|
210
|
-
allow(
|
210
|
+
allow(jira_api).to receive(:preview?).and_return(false)
|
211
211
|
|
212
212
|
# TODO: create stubs without each `it` expected
|
213
|
-
allow(Embulk::Input::
|
213
|
+
allow(Embulk::Input::JiraApi::Client).to receive(:setup).and_return(jira_api)
|
214
214
|
|
215
215
|
0.step(total_count, max_result) do |start_at|
|
216
216
|
issues = jira_issues[start_at..(start_at + max_result - 1)]
|
@@ -236,22 +236,76 @@ describe Embulk::Input::JiraInputPlugin do
|
|
236
236
|
it 'returns commit report' do
|
237
237
|
expect(subject).to eq commit_report
|
238
238
|
end
|
239
|
+
|
240
|
+
end
|
241
|
+
|
242
|
+
describe "preview" do
|
243
|
+
let(:plugin) { described_class.new(task, nil, nil, page_builder) }
|
244
|
+
let(:task) do
|
245
|
+
{
|
246
|
+
"jql" => jql,
|
247
|
+
"attributes" => {"project.key" => "string"}
|
248
|
+
}
|
249
|
+
end
|
250
|
+
let(:page_builder) { double("page_builder") }
|
251
|
+
let(:jira_api) { Embulk::Input::JiraApi::Client.new }
|
252
|
+
let(:jira_issues) { [Embulk::Input::JiraApi::Issue.new(attributes)] }
|
253
|
+
let(:attributes) do
|
254
|
+
{
|
255
|
+
"id" => "100",
|
256
|
+
"jira_key" => "FOO-100",
|
257
|
+
"fields" =>
|
258
|
+
{
|
259
|
+
"project" => {
|
260
|
+
"name" => project_name,
|
261
|
+
"key" => project_name,
|
262
|
+
},
|
263
|
+
"comment" => {
|
264
|
+
"total" => 0,
|
265
|
+
"comments" => []
|
266
|
+
}
|
267
|
+
}
|
268
|
+
}
|
269
|
+
end
|
270
|
+
|
271
|
+
|
272
|
+
subject { plugin.run }
|
273
|
+
|
274
|
+
before do
|
275
|
+
allow(Embulk::Input::JiraApi::Client).to receive(:setup).and_return(jira_api)
|
276
|
+
allow(plugin).to receive(:logger).and_return(::Logger.new(File::NULL))
|
277
|
+
allow(plugin).to receive(:preview?).and_return(true)
|
278
|
+
allow(jira_api).to receive(:search_issues).and_return(jira_issues)
|
279
|
+
allow(page_builder).to receive(:add)
|
280
|
+
allow(page_builder).to receive(:finish)
|
281
|
+
end
|
282
|
+
|
283
|
+
it "max_results with PREVIEW_RECORDS_COUNT" do
|
284
|
+
expect(jira_api).to receive(:search_issues).with(jql, max_results: Embulk::Input::Jira::PREVIEW_RECORDS_COUNT)
|
285
|
+
subject
|
286
|
+
end
|
287
|
+
|
288
|
+
it "call page_builder.add and page_builder.finish" do
|
289
|
+
expect(page_builder).to receive(:add).exactly(jira_issues.length).times
|
290
|
+
expect(page_builder).to receive(:finish)
|
291
|
+
subject
|
292
|
+
end
|
239
293
|
end
|
240
294
|
|
241
295
|
describe ".logger" do
|
242
|
-
let(:logger) {
|
296
|
+
let(:logger) { described_class.logger }
|
243
297
|
|
244
298
|
subject { logger }
|
245
299
|
|
246
|
-
it { is_expected.to be_a(Logger) }
|
300
|
+
it { is_expected.to be_a(Embulk::Logger) }
|
247
301
|
end
|
248
302
|
|
249
303
|
describe "#logger" do
|
250
|
-
let(:instance) {
|
304
|
+
let(:instance) { described_class.new({}, nil, nil, nil) }
|
251
305
|
let(:logger) { instance.logger }
|
252
306
|
|
253
307
|
subject { logger }
|
254
308
|
|
255
|
-
it { is_expected.to be_a(Logger) }
|
309
|
+
it { is_expected.to be_a(Embulk::Logger) }
|
256
310
|
end
|
257
311
|
end
|
data/spec/embulk_spec.rb
CHANGED
@@ -11,11 +11,11 @@ in:
|
|
11
11
|
before do
|
12
12
|
config_file.puts config
|
13
13
|
config_file.close
|
14
|
-
allow(org.embulk.spi.Exec).to
|
14
|
+
allow(org.embulk.spi.Exec).to receive(:isPreview).and_return(true)
|
15
15
|
end
|
16
16
|
|
17
17
|
subject {
|
18
|
-
|
18
|
+
capture(:out) do
|
19
19
|
Embulk.run ["preview", config_file.path]
|
20
20
|
end
|
21
21
|
}
|
@@ -1,5 +1,18 @@
|
|
1
1
|
module StdoutAndErrCapture
|
2
|
-
def
|
2
|
+
def capture(output = :out, &block)
|
3
|
+
_, out = swap_io(output, &block)
|
4
|
+
out
|
5
|
+
end
|
6
|
+
|
7
|
+
def silence(&block)
|
8
|
+
block_result = nil
|
9
|
+
swap_io(:out) do
|
10
|
+
block_result,_ = swap_io(:err, &block)
|
11
|
+
end
|
12
|
+
block_result
|
13
|
+
end
|
14
|
+
|
15
|
+
def swap_io(output = :out, &block)
|
3
16
|
java_import 'java.io.PrintStream'
|
4
17
|
java_import 'java.io.ByteArrayOutputStream'
|
5
18
|
java_import 'java.lang.System'
|
@@ -12,21 +25,21 @@ module StdoutAndErrCapture
|
|
12
25
|
case output
|
13
26
|
when :out
|
14
27
|
$stdout = ruby_buf
|
28
|
+
System.setOut(PrintStream.new(java_buf))
|
15
29
|
when :err
|
16
30
|
$stderr = ruby_buf
|
31
|
+
System.setErr(PrintStream.new(java_buf))
|
17
32
|
end
|
18
|
-
System.setOut(PrintStream.new(java_buf))
|
19
|
-
|
20
|
-
block.call
|
21
33
|
|
22
|
-
ruby_buf.string + java_buf.toString
|
34
|
+
[block.call, ruby_buf.string + java_buf.toString]
|
23
35
|
ensure
|
24
|
-
System.setOut(java_original_stream)
|
25
36
|
case output
|
26
37
|
when :out
|
27
38
|
$stdout = ruby_original_stream
|
39
|
+
System.setOut(java_original_stream)
|
28
40
|
when :err
|
29
41
|
$stderr = ruby_original_stream
|
42
|
+
System.setErr(java_original_stream)
|
30
43
|
end
|
31
44
|
end
|
32
45
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: embulk-input-jira
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- uu59
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2015-06-
|
12
|
+
date: 2015-06-24 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
@@ -112,15 +112,14 @@ files:
|
|
112
112
|
- Rakefile
|
113
113
|
- embulk-input-jira.gemspec
|
114
114
|
- lib/embulk/input/jira.rb
|
115
|
-
- lib/embulk/input/
|
116
|
-
- lib/embulk/input/
|
117
|
-
- lib/embulk/input/
|
118
|
-
- lib/embulk/input/jira_input_plugin.rb
|
115
|
+
- lib/embulk/input/jira_api.rb
|
116
|
+
- lib/embulk/input/jira_api/client.rb
|
117
|
+
- lib/embulk/input/jira_api/issue.rb
|
119
118
|
- lib/embulk/input/jira_input_plugin_utils.rb
|
120
119
|
- spec/embulk/input/jira-input-plugin-utils_spec.rb
|
121
|
-
- spec/embulk/input/
|
122
|
-
- spec/embulk/input/
|
123
|
-
- spec/embulk/input/
|
120
|
+
- spec/embulk/input/jira_api/client_spec.rb
|
121
|
+
- spec/embulk/input/jira_api/issue_spec.rb
|
122
|
+
- spec/embulk/input/jira_spec.rb
|
124
123
|
- spec/embulk_spec.rb
|
125
124
|
- spec/spec_helper.rb
|
126
125
|
- spec/support/prepare_embulk.rb
|
@@ -151,9 +150,9 @@ specification_version: 4
|
|
151
150
|
summary: Jira input plugin for Embulk
|
152
151
|
test_files:
|
153
152
|
- spec/embulk/input/jira-input-plugin-utils_spec.rb
|
154
|
-
- spec/embulk/input/
|
155
|
-
- spec/embulk/input/
|
156
|
-
- spec/embulk/input/
|
153
|
+
- spec/embulk/input/jira_api/client_spec.rb
|
154
|
+
- spec/embulk/input/jira_api/issue_spec.rb
|
155
|
+
- spec/embulk/input/jira_spec.rb
|
157
156
|
- spec/embulk_spec.rb
|
158
157
|
- spec/spec_helper.rb
|
159
158
|
- spec/support/prepare_embulk.rb
|
@@ -1,135 +0,0 @@
|
|
1
|
-
require "embulk/input/jira_input_plugin_utils"
|
2
|
-
require "embulk/input/jira/api"
|
3
|
-
require "logger"
|
4
|
-
require "time"
|
5
|
-
|
6
|
-
module Embulk
|
7
|
-
module Input
|
8
|
-
class JiraInputPlugin < InputPlugin
|
9
|
-
PER_PAGE = 50
|
10
|
-
GUESS_RECORDS_COUNT = 10
|
11
|
-
PREVIEW_RECORDS_COUNT = 15
|
12
|
-
|
13
|
-
Plugin.register_input("jira", self)
|
14
|
-
|
15
|
-
def self.transaction(config, &control)
|
16
|
-
task = {
|
17
|
-
"username" => config.param("username", :string),
|
18
|
-
"password" => config.param("password", :string),
|
19
|
-
"uri" => config.param("uri", :string),
|
20
|
-
"jql" => config.param("jql", :string),
|
21
|
-
}
|
22
|
-
|
23
|
-
attributes = {}
|
24
|
-
columns = config.param("columns", :array).map do |column|
|
25
|
-
name = column["name"]
|
26
|
-
type = column["type"].to_sym
|
27
|
-
attributes[name] = type
|
28
|
-
Column.new(nil, name, type, column["format"])
|
29
|
-
end
|
30
|
-
|
31
|
-
task["attributes"] = attributes
|
32
|
-
|
33
|
-
resume(task, columns, 1, &control)
|
34
|
-
end
|
35
|
-
|
36
|
-
def self.resume(task, columns, count, &control)
|
37
|
-
commit_reports = yield(task, columns, count)
|
38
|
-
|
39
|
-
next_config_diff = {}
|
40
|
-
return next_config_diff
|
41
|
-
end
|
42
|
-
|
43
|
-
def self.guess(config)
|
44
|
-
# TODO: api_version should be 2 (the latest version)
|
45
|
-
# auth_type should be specified from config. (The future task)
|
46
|
-
|
47
|
-
username = config.param("username", :string)
|
48
|
-
password = config.param("password", :string)
|
49
|
-
uri = config.param("uri", :string)
|
50
|
-
api_version = "latest"
|
51
|
-
auth_type = "basic"
|
52
|
-
jql = config.param("jql", :string)
|
53
|
-
|
54
|
-
jira = Jira::Api.setup do |jira_config|
|
55
|
-
jira_config.username = username
|
56
|
-
jira_config.password = password
|
57
|
-
jira_config.uri = uri
|
58
|
-
jira_config.api_version = api_version
|
59
|
-
jira_config.auth_type = auth_type
|
60
|
-
end
|
61
|
-
|
62
|
-
# TODO: we use 0..10 issues to guess config?
|
63
|
-
records = jira.search_issues(jql, max_results: GUESS_RECORDS_COUNT).map do |issue|
|
64
|
-
issue.to_record
|
65
|
-
end
|
66
|
-
|
67
|
-
columns = JiraInputPluginUtils.guess_columns(records)
|
68
|
-
|
69
|
-
guessed_config = {
|
70
|
-
"columns" => columns,
|
71
|
-
}
|
72
|
-
|
73
|
-
return guessed_config
|
74
|
-
end
|
75
|
-
|
76
|
-
def init
|
77
|
-
@attributes = task["attributes"]
|
78
|
-
@jira = Jira::Api.setup do |config|
|
79
|
-
config.username = task["username"]
|
80
|
-
config.password = task["password"]
|
81
|
-
config.uri = task["uri"]
|
82
|
-
config.api_version = "latest"
|
83
|
-
config.auth_type = :basic
|
84
|
-
end
|
85
|
-
@jql = task["jql"]
|
86
|
-
end
|
87
|
-
|
88
|
-
def run
|
89
|
-
# NOTE: This is workaround for "org.embulk.spi.Exec.isPreview"
|
90
|
-
# TODO: Extract process for preview command to method
|
91
|
-
if org.embulk.spi.Exec.session().isPreview()
|
92
|
-
options = {max_results: PREVIEW_RECORDS_COUNT}
|
93
|
-
total_count = PREVIEW_RECORDS_COUNT
|
94
|
-
last_page = 1
|
95
|
-
logger.debug "For preview mode, JIRA input plugin fetches records at most #{PREVIEW_RECORDS_COUNT}"
|
96
|
-
else
|
97
|
-
options = {}
|
98
|
-
total_count = @jira.total_count(@jql)
|
99
|
-
last_page = (total_count.to_f / PER_PAGE).ceil
|
100
|
-
end
|
101
|
-
|
102
|
-
0.step(total_count, PER_PAGE).with_index(1) do |start_at, page|
|
103
|
-
logger.debug "Fetching #{page} / #{last_page} page"
|
104
|
-
@jira.search_issues(@jql, options.merge(start_at: start_at)).each do |issue|
|
105
|
-
values = @attributes.map do |(attribute_name, type)|
|
106
|
-
JiraInputPluginUtils.cast(issue[attribute_name], type)
|
107
|
-
end
|
108
|
-
|
109
|
-
page_builder.add(values)
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
page_builder.finish
|
114
|
-
|
115
|
-
commit_report = {}
|
116
|
-
return commit_report
|
117
|
-
end
|
118
|
-
|
119
|
-
def self.logger
|
120
|
-
@logger ||=
|
121
|
-
begin
|
122
|
-
logger = Logger.new($stdout)
|
123
|
-
logger.formatter = proc do |severity, datetime, progname, msg|
|
124
|
-
"#{datetime.strftime("%Y-%m-%d %H:%M:%S.%L %z")} [#{severity}] #{msg}\n"
|
125
|
-
end
|
126
|
-
logger
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
def logger
|
131
|
-
self.class.logger
|
132
|
-
end
|
133
|
-
end
|
134
|
-
end
|
135
|
-
end
|