git-storyid 0.3.5 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1a9a29277089575a0e5895d972606d9557b2d858
4
- data.tar.gz: 63d5358ab8337ae52af55d557828d12759824aef
3
+ metadata.gz: 56549fea6495f60b2c872b7decff12ced0a7b3be
4
+ data.tar.gz: ca961d3da3235eaaa74efac733dcb4cb00e3c24e
5
5
  SHA512:
6
- metadata.gz: ad3882859335767c3b38bd5d3c6e57f672b08678ea995cd4af552b4c71defb783b7deade122a4696a280f3dc63a73892ee36e933cfa197adaad737fb346c872d
7
- data.tar.gz: 1d7e393f9840d833d7aa3027aee8a1947d45e57b8dea53f2f2f3c88c58937d66722ef155a1680025a25fd44afd1f9a11e1c8bff2a6e385bb9303a12790a55159
6
+ metadata.gz: 9079a32c507af4e585b03377658b01809f44d74bf30f6ecc9cfbdc055787ade41b70b72def15b0d969697379d96bef69ef0438b5b3f7c7ac28278e2bf31196c4
7
+ data.tar.gz: 3de0ae28685b01233941147a85ceae06c8d04ea8e78c5841ce22efc91b8dc8cf1070758e83bee3c7b212479d2509826f8fe92827cca312b615fc43230ae7b2cb
data/Gemfile CHANGED
@@ -1,6 +1,8 @@
1
1
  source "http://rubygems.org"
2
2
 
3
3
  gem "pivotal-tracker"
4
+ gem "jira-ruby"
5
+
4
6
  group :development do
5
7
  gem "webmock"
6
8
  gem "debugger", :platform => "ruby_19"
@@ -8,4 +10,6 @@ group :development do
8
10
  gem "rspec"
9
11
  gem "jeweler"
10
12
  gem "hashie"
13
+ gem "pry-byebug", require: false
14
+ gem "http_logger"
11
15
  end
@@ -1,56 +1,136 @@
1
1
  GEM
2
2
  remote: http://rubygems.org/
3
3
  specs:
4
- addressable (2.3.2)
5
- builder (3.0.0)
6
- columnize (0.3.6)
7
- crack (0.3.1)
8
- debugger (1.2.1)
4
+ activesupport (5.0.1)
5
+ concurrent-ruby (~> 1.0, >= 1.0.2)
6
+ i18n (~> 0.7)
7
+ minitest (~> 5.1)
8
+ tzinfo (~> 1.1)
9
+ addressable (2.5.0)
10
+ public_suffix (~> 2.0, >= 2.0.2)
11
+ builder (3.2.2)
12
+ byebug (9.0.5)
13
+ coderay (1.1.1)
14
+ columnize (0.9.0)
15
+ concurrent-ruby (1.0.3)
16
+ crack (0.4.3)
17
+ safe_yaml (~> 1.0.0)
18
+ debugger (1.6.8)
9
19
  columnize (>= 0.3.1)
10
- debugger-linecache (~> 1.1.1)
11
- debugger-ruby_core_source (~> 1.1.4)
12
- debugger-linecache (1.1.2)
13
- debugger-ruby_core_source (>= 1.1.1)
14
- debugger-ruby_core_source (1.1.4)
15
- diff-lcs (1.2.1)
16
- git (1.2.6)
17
- happymapper (0.4.0)
18
- libxml-ruby (~> 2.0)
19
- hashie (1.2.0)
20
- jeweler (2.0.1)
21
- bundler (~> 1.0)
20
+ debugger-linecache (~> 1.2.0)
21
+ debugger-ruby_core_source (~> 1.3.5)
22
+ debugger-linecache (1.2.0)
23
+ debugger-ruby_core_source (1.3.8)
24
+ descendants_tracker (0.0.4)
25
+ thread_safe (~> 0.3, >= 0.3.1)
26
+ diff-lcs (1.2.5)
27
+ domain_name (0.5.20161129)
28
+ unf (>= 0.0.5, < 1.0.0)
29
+ faraday (0.9.2)
30
+ multipart-post (>= 1.2, < 3)
31
+ git (1.3.0)
32
+ github_api (0.11.3)
33
+ addressable (~> 2.3)
34
+ descendants_tracker (~> 0.0.1)
35
+ faraday (~> 0.8, < 0.10)
36
+ hashie (>= 1.2)
37
+ multi_json (>= 1.7.5, < 2.0)
38
+ nokogiri (~> 1.6.0)
39
+ oauth2
40
+ hashdiff (0.3.1)
41
+ hashie (3.4.6)
42
+ highline (1.7.8)
43
+ http-cookie (1.0.3)
44
+ domain_name (~> 0.5)
45
+ http_logger (0.5.1)
46
+ i18n (0.7.0)
47
+ jeweler (2.3.1)
48
+ builder
49
+ bundler (>= 1.0)
22
50
  git (>= 1.2.5)
51
+ github_api (~> 0.11.0)
52
+ highline (>= 1.6.15)
53
+ nokogiri (>= 1.5.10)
54
+ psych (~> 2.2)
23
55
  rake
24
56
  rdoc
25
- json (1.8.1)
26
- libxml-ruby (2.7.0)
27
- metaclass (0.0.1)
28
- mime-types (1.19)
29
- mocha (0.13.2)
57
+ semver
58
+ jira-ruby (1.1.3)
59
+ activesupport
60
+ oauth (~> 0.5, >= 0.5.0)
61
+ jwt (1.5.6)
62
+ metaclass (0.0.4)
63
+ method_source (0.8.2)
64
+ mime-types (3.1)
65
+ mime-types-data (~> 3.2015)
66
+ mime-types-data (3.2016.0521)
67
+ mini_portile2 (2.1.0)
68
+ minitest (5.10.1)
69
+ mocha (1.2.1)
30
70
  metaclass (~> 0.0.1)
31
- nokogiri (1.5.5)
32
- pivotal-tracker (0.5.4)
71
+ multi_json (1.12.1)
72
+ multi_xml (0.6.0)
73
+ multipart-post (2.0.0)
74
+ netrc (0.11.0)
75
+ nokogiri (1.6.8.1)
76
+ mini_portile2 (~> 2.1.0)
77
+ nokogiri-happymapper (0.5.9)
78
+ nokogiri (~> 1.5)
79
+ oauth (0.5.1)
80
+ oauth2 (1.2.0)
81
+ faraday (>= 0.8, < 0.10)
82
+ jwt (~> 1.0)
83
+ multi_json (~> 1.3)
84
+ multi_xml (~> 0.5)
85
+ rack (>= 1.2, < 3)
86
+ pivotal-tracker (0.5.13)
33
87
  builder
34
- happymapper (>= 0.3.2)
35
- nokogiri (>= 1.4.3)
36
- nokogiri (~> 1.4)
37
- rest-client (~> 1.6.0)
38
- rake (10.3.2)
39
- rdoc (4.1.1)
40
- json (~> 1.4)
41
- rest-client (1.6.7)
42
- mime-types (>= 1.16)
43
- rspec (2.13.0)
44
- rspec-core (~> 2.13.0)
45
- rspec-expectations (~> 2.13.0)
46
- rspec-mocks (~> 2.13.0)
47
- rspec-core (2.13.0)
48
- rspec-expectations (2.13.0)
49
- diff-lcs (>= 1.1.3, < 2.0)
50
- rspec-mocks (2.13.0)
51
- webmock (1.8.7)
52
- addressable (>= 2.2.7)
53
- crack (>= 0.1.7)
88
+ crack
89
+ nokogiri (>= 1.5.5)
90
+ nokogiri-happymapper (>= 0.5.4)
91
+ rest-client (>= 1.8.0)
92
+ pry (0.10.4)
93
+ coderay (~> 1.1.0)
94
+ method_source (~> 0.8.1)
95
+ slop (~> 3.4)
96
+ pry-byebug (3.4.0)
97
+ byebug (~> 9.0)
98
+ pry (~> 0.10)
99
+ psych (2.2.2)
100
+ public_suffix (2.0.4)
101
+ rack (2.0.1)
102
+ rake (12.0.0)
103
+ rdoc (5.0.0)
104
+ rest-client (2.0.0)
105
+ http-cookie (>= 1.0.2, < 2.0)
106
+ mime-types (>= 1.16, < 4.0)
107
+ netrc (~> 0.8)
108
+ rspec (3.5.0)
109
+ rspec-core (~> 3.5.0)
110
+ rspec-expectations (~> 3.5.0)
111
+ rspec-mocks (~> 3.5.0)
112
+ rspec-core (3.5.4)
113
+ rspec-support (~> 3.5.0)
114
+ rspec-expectations (3.5.0)
115
+ diff-lcs (>= 1.2.0, < 2.0)
116
+ rspec-support (~> 3.5.0)
117
+ rspec-mocks (3.5.0)
118
+ diff-lcs (>= 1.2.0, < 2.0)
119
+ rspec-support (~> 3.5.0)
120
+ rspec-support (3.5.0)
121
+ safe_yaml (1.0.4)
122
+ semver (1.0.1)
123
+ slop (3.6.0)
124
+ thread_safe (0.3.5)
125
+ tzinfo (1.2.2)
126
+ thread_safe (~> 0.1)
127
+ unf (0.1.4)
128
+ unf_ext
129
+ unf_ext (0.0.7.2)
130
+ webmock (2.3.1)
131
+ addressable (>= 2.3.6)
132
+ crack (>= 0.3.2)
133
+ hashdiff
54
134
 
55
135
  PLATFORMS
56
136
  ruby
@@ -58,8 +138,14 @@ PLATFORMS
58
138
  DEPENDENCIES
59
139
  debugger
60
140
  hashie
141
+ http_logger
61
142
  jeweler
143
+ jira-ruby
62
144
  mocha
63
145
  pivotal-tracker
146
+ pry-byebug
64
147
  rspec
65
148
  webmock
149
+
150
+ BUNDLED WITH
151
+ 1.13.3
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.5
1
+ 0.4.0
@@ -2,19 +2,19 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
- # stub: git-storyid 0.3.5 ruby lib
5
+ # stub: git-storyid 0.4.0 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
- s.name = "git-storyid"
9
- s.version = "0.3.5"
8
+ s.name = "git-storyid".freeze
9
+ s.version = "0.4.0"
10
10
 
11
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
- s.require_paths = ["lib"]
13
- s.authors = ["Bogdan Gusiev"]
14
- s.date = "2016-01-13"
15
- s.description = "Helps include pivotal story id and description in commit"
16
- s.email = "agresso@gmail.com"
17
- s.executables = ["git-storyid"]
11
+ s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
12
+ s.require_paths = ["lib".freeze]
13
+ s.authors = ["Bogdan Gusiev".freeze]
14
+ s.date = "2017-01-11"
15
+ s.description = "Helps include pivotal story id and description in commit".freeze
16
+ s.email = "agresso@gmail.com".freeze
17
+ s.executables = ["git-storyid".freeze]
18
18
  s.extra_rdoc_files = [
19
19
  "LICENSE.txt",
20
20
  "README.md"
@@ -32,42 +32,52 @@ Gem::Specification.new do |s|
32
32
  "git-storyid.gemspec",
33
33
  "lib/git-storyid.rb",
34
34
  "lib/git_storyid.rb",
35
+ "spec/git_storyid/jira_spec.rb",
35
36
  "spec/git_storyid_spec.rb",
36
37
  "spec/spec_helper.rb"
37
38
  ]
38
- s.homepage = "http://github.com/bogdan/git-storyid"
39
- s.licenses = ["MIT"]
40
- s.rubygems_version = "2.4.7"
41
- s.summary = "Attach commits to pivotal stories"
39
+ s.homepage = "http://github.com/bogdan/git-storyid".freeze
40
+ s.licenses = ["MIT".freeze]
41
+ s.rubygems_version = "2.6.7".freeze
42
+ s.summary = "Attach commits to pivotal stories".freeze
42
43
 
43
44
  if s.respond_to? :specification_version then
44
45
  s.specification_version = 4
45
46
 
46
47
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
47
- s.add_runtime_dependency(%q<pivotal-tracker>, [">= 0"])
48
- s.add_development_dependency(%q<webmock>, [">= 0"])
49
- s.add_development_dependency(%q<debugger>, [">= 0"])
50
- s.add_development_dependency(%q<mocha>, [">= 0"])
51
- s.add_development_dependency(%q<rspec>, [">= 0"])
52
- s.add_development_dependency(%q<jeweler>, [">= 0"])
53
- s.add_development_dependency(%q<hashie>, [">= 0"])
48
+ s.add_runtime_dependency(%q<pivotal-tracker>.freeze, [">= 0"])
49
+ s.add_runtime_dependency(%q<jira-ruby>.freeze, [">= 0"])
50
+ s.add_development_dependency(%q<webmock>.freeze, [">= 0"])
51
+ s.add_development_dependency(%q<debugger>.freeze, [">= 0"])
52
+ s.add_development_dependency(%q<mocha>.freeze, [">= 0"])
53
+ s.add_development_dependency(%q<rspec>.freeze, [">= 0"])
54
+ s.add_development_dependency(%q<jeweler>.freeze, [">= 0"])
55
+ s.add_development_dependency(%q<hashie>.freeze, [">= 0"])
56
+ s.add_development_dependency(%q<pry-byebug>.freeze, [">= 0"])
57
+ s.add_development_dependency(%q<http_logger>.freeze, [">= 0"])
54
58
  else
55
- s.add_dependency(%q<pivotal-tracker>, [">= 0"])
56
- s.add_dependency(%q<webmock>, [">= 0"])
57
- s.add_dependency(%q<debugger>, [">= 0"])
58
- s.add_dependency(%q<mocha>, [">= 0"])
59
- s.add_dependency(%q<rspec>, [">= 0"])
60
- s.add_dependency(%q<jeweler>, [">= 0"])
61
- s.add_dependency(%q<hashie>, [">= 0"])
59
+ s.add_dependency(%q<pivotal-tracker>.freeze, [">= 0"])
60
+ s.add_dependency(%q<jira-ruby>.freeze, [">= 0"])
61
+ s.add_dependency(%q<webmock>.freeze, [">= 0"])
62
+ s.add_dependency(%q<debugger>.freeze, [">= 0"])
63
+ s.add_dependency(%q<mocha>.freeze, [">= 0"])
64
+ s.add_dependency(%q<rspec>.freeze, [">= 0"])
65
+ s.add_dependency(%q<jeweler>.freeze, [">= 0"])
66
+ s.add_dependency(%q<hashie>.freeze, [">= 0"])
67
+ s.add_dependency(%q<pry-byebug>.freeze, [">= 0"])
68
+ s.add_dependency(%q<http_logger>.freeze, [">= 0"])
62
69
  end
63
70
  else
64
- s.add_dependency(%q<pivotal-tracker>, [">= 0"])
65
- s.add_dependency(%q<webmock>, [">= 0"])
66
- s.add_dependency(%q<debugger>, [">= 0"])
67
- s.add_dependency(%q<mocha>, [">= 0"])
68
- s.add_dependency(%q<rspec>, [">= 0"])
69
- s.add_dependency(%q<jeweler>, [">= 0"])
70
- s.add_dependency(%q<hashie>, [">= 0"])
71
+ s.add_dependency(%q<pivotal-tracker>.freeze, [">= 0"])
72
+ s.add_dependency(%q<jira-ruby>.freeze, [">= 0"])
73
+ s.add_dependency(%q<webmock>.freeze, [">= 0"])
74
+ s.add_dependency(%q<debugger>.freeze, [">= 0"])
75
+ s.add_dependency(%q<mocha>.freeze, [">= 0"])
76
+ s.add_dependency(%q<rspec>.freeze, [">= 0"])
77
+ s.add_dependency(%q<jeweler>.freeze, [">= 0"])
78
+ s.add_dependency(%q<hashie>.freeze, [">= 0"])
79
+ s.add_dependency(%q<pry-byebug>.freeze, [">= 0"])
80
+ s.add_dependency(%q<http_logger>.freeze, [">= 0"])
71
81
  end
72
82
  end
73
83
 
@@ -1,8 +1,8 @@
1
1
  require "readline"
2
2
  require "optparse"
3
- require "pivotal_tracker"
4
3
  require "yaml"
5
4
  require "open3"
5
+ require 'io/console'
6
6
 
7
7
  class GitStoryid
8
8
 
@@ -10,7 +10,17 @@ class GitStoryid
10
10
  new(*args).run
11
11
  end
12
12
 
13
+ def self.output(message)
14
+ puts message
15
+ end
16
+
17
+ def output(message)
18
+ self.class.output(message)
19
+ end
20
+
21
+
13
22
  def initialize(*arguments)
23
+ @tracker = Configuration.build
14
24
  @git_options = []
15
25
  parser = OptionParser.new do |opts|
16
26
  opts.banner = "Do git commit with information from pivotal story"
@@ -28,50 +38,43 @@ class GitStoryid
28
38
 
29
39
  unless arguments.empty?
30
40
  @stories = arguments.map do |argument|
31
- Configuration.project.stories.find(argument)
41
+ @tracker.find_story_by_id(argument)
32
42
  end
33
43
  end
34
44
  end
35
45
 
36
- def all_stories
37
- @all_stories ||= Configuration.project.stories.all(
38
- :owner => Configuration.me,
39
- :state => %w(started finished delivered),
40
- :limit => 30
41
- )
42
- end
43
-
44
46
  def readline_stories_if_not_present
45
47
  if !@stories || @stories.empty?
46
48
  quit_if_no_stories
47
49
  output stories_menu
48
50
  @stories = readline_story_ids.map do |index|
49
- if index > 1_000_000
50
- # Consider it a direct story id
51
- Configuration.project.stories.find(index)
52
- else
53
- all_stories[index - 1] || (quit("Story index #{index} not found."))
54
- end
51
+ fetch_story(index) || quit("Story #{index} was not found.")
55
52
  end
56
53
  end
57
54
  rescue RefetchStories
58
- @all_stories = nil
55
+ @tracker.reset
56
+ @stories = nil
59
57
  readline_stories_if_not_present
60
58
  end
61
59
 
62
- def output(message)
63
- puts message
60
+ def fetch_story(index)
61
+ if (1..100).include?(index.to_i)
62
+ @tracker.all_stories[index.to_i - 1]
63
+ else
64
+ # Consider it a direct story id
65
+ @tracker.find_story_by_id(index)
66
+ end
64
67
  end
65
68
 
66
69
  def quit_if_no_stories
67
- if all_stories.empty?
70
+ if @tracker.all_stories.empty?
68
71
  quit "No stories started and owned by you."
69
72
  end
70
73
  end
71
74
 
72
75
  def stories_menu
73
76
  result = ""
74
- all_stories.each_with_index do |story, index|
77
+ @tracker.all_stories.each_with_index do |story, index|
75
78
  result << "[#{index + 1}] #{story.name}\n"
76
79
  end
77
80
  result << "\n"
@@ -86,8 +89,11 @@ class GitStoryid
86
89
  ids = input.split(/\s*,\s*/).reject do |string|
87
90
  string.empty?
88
91
  end
89
- quit("Cancelling.") if ids.empty?
90
- ids.map {|id| id.to_i }
92
+ if ids.empty?
93
+ quit("Cancelling.")
94
+ else
95
+ ids
96
+ end
91
97
  end
92
98
 
93
99
  def readline
@@ -118,7 +124,7 @@ class GitStoryid
118
124
  message += @custom_message.to_s + "\n\n"
119
125
  end
120
126
  message += @stories.map do |story|
121
- "#{story.story_type.capitalize}: " + story.name.strip
127
+ "#{story.type.capitalize}: " + story.name.strip
122
128
  end.join("\n\n")
123
129
  message
124
130
  end
@@ -126,7 +132,7 @@ class GitStoryid
126
132
  def finish_story_prefix(story)
127
133
  return "Delivers " if @deliver_stories
128
134
  return "" unless @finish_stories
129
- story.story_type == "bug" ? "Fixes " : "Finishes "
135
+ story.type == "bug" ? "Fixes " : "Finishes "
130
136
  end
131
137
 
132
138
  def execute(*args)
@@ -139,111 +145,186 @@ class GitStoryid
139
145
  end
140
146
  end
141
147
 
148
+ class Configuration
149
+
150
+ def self.build
151
+ load_config
152
+ ensure_full_config
153
+ TRACKER_CONFIG[engine][:class].new(@config)
154
+ end
142
155
 
143
- module Configuration
144
156
  class << self
145
157
 
146
- def config=(config)
147
- @config = config
158
+ def load_config
159
+ @config ||= load_config_from
160
+ end
161
+
162
+ def engine
163
+ e = @config[:engine]
164
+ e ? e.to_sym : nil
165
+ end
166
+
167
+ def ensure_full_config
168
+ @config[:engine] = read_configuration_value("Engine (pivotal/jira)") unless engine
169
+ tracker_config = TRACKER_CONFIG[engine]
170
+
171
+ return if tracker_config && @config.keys.sort == (tracker_config[:options].keys + [:engine]).sort
172
+
173
+ tracker_config[:options].each do |key, label|
174
+ @config[key] = read_configuration_value(label, key == :password)
175
+ end
176
+
177
+ File.open(project_config_path, "w") do |file|
178
+ file.write YAML.dump(@config)
179
+ end
180
+ output "Writing config to #{project_config_path}"
181
+ end
182
+
183
+ def read_configuration_value(label, hidden = false)
184
+ label = "#{label}: "
185
+ if hidden
186
+ print label
187
+ password = STDIN.noecho(&:gets).chomp
188
+ puts ''
189
+ password
190
+ else
191
+ Readline.readline(label, true)
192
+ end
193
+ end
194
+
195
+ def load_config_from
196
+ return {} unless project_config_path
197
+ if File.exists?(project_config_path)
198
+ YAML.load(File.read(project_config_path)) || {}
199
+ else
200
+ {}
201
+ end
202
+ end
203
+
204
+ def project_config_path
205
+ @project_config_path ||= find_project_config
206
+ end
207
+ def find_project_config
208
+ dirs = File.split(Dir.pwd)
209
+ until dirs.empty? || File.exists?(File.join(dirs, FILENAME))
210
+ dirs.pop
211
+ end
212
+ unless dirs.empty?
213
+ File.join(dirs, FILENAME)
214
+ else
215
+ File.join(Dir.pwd, FILENAME)
216
+ end
217
+ end
148
218
  end
149
219
 
150
- def read
151
- return if @loaded
152
- load_config
153
- ensure_full_config
220
+ def initialize(config)
221
+ @config = config
154
222
  setup_api_client
155
- @loaded = true
156
223
  end
157
224
 
158
- def load_config
159
- @config ||= {}
160
- @config.merge!(load_config_from(global_config_path))
161
- @project_config = load_config_from(project_config_path)
162
- @config.merge!(@project_config)
225
+ def all_stories
226
+ @all_stories ||= fetch_all_stories.map do |story|
227
+ serialize_issue(story)
228
+ end
163
229
  end
164
230
 
231
+ def reset
232
+ @all_stories = nil
233
+ end
234
+
235
+ def self.output(message)
236
+ GitStoryid.output(message)
237
+ end
238
+
239
+
240
+ FILENAME = %w(.git-storyid)
241
+
242
+ end
243
+
244
+ class SerializedIssue < Struct.new(:id, :type, :name)
245
+ end
246
+ class PivotalConfiguration < Configuration
247
+
165
248
  def setup_api_client
249
+ require "pivotal_tracker"
166
250
  PivotalTracker::Client.token = @config['api_token']
167
- PivotalTracker::Client.use_ssl = @config['use_ssl'] ? @config['use_ssl'] : false
168
- end
169
-
170
- def ensure_full_config
171
- changed = false
172
- {
173
- "api_token" => "Api token (https://www.pivotaltracker.com/profile)",
174
- "use_ssl" => "Use SSL (y/n)",
175
- "me" => "Your pivotal initials (e.g. BG)",
176
- "project_id" => "Project ID"
177
- }.each do |key, label|
178
- if @config[key].nil?
179
- changed = true
180
- value = Readline.readline("#{label}: ", true)
181
- @project_config[key] = format_config_value(value)
182
- end
183
- end
184
- if changed
185
- File.open("./.pivotalrc", "w") do |file|
186
- file.write YAML.dump(@project_config)
187
- end
188
- @config.merge!(@project_config)
189
- #output "Writing config to .pivotalrc"
190
- end
251
+ PivotalTracker::Client.use_ssl = true
191
252
  end
192
253
 
193
- def format_config_value(value)
194
- case value
195
- when "y"
196
- true
197
- when "n"
198
- false
199
- else
200
- value
201
- end
254
+ def me
255
+ @me ||= @config['me']
202
256
  end
203
257
 
204
- def load_config_from(path)
205
- return {} unless path
206
- file = File.join path,'.pivotalrc'
207
- if File.exists?(file)
208
- YAML.load(File.read(file)) || {}
209
- else
210
- {}
211
- end
258
+ def fetch_all_stories
259
+ project.stories.all(
260
+ :owner => me,
261
+ :state => %w(started finished delivered),
262
+ :limit => 30
263
+ )
212
264
  end
213
265
 
266
+ def find_story_by_id(id)
267
+ serialize_issue(@tracker.project.stories.find(id))
268
+ end
269
+
270
+ def serialize_issue(issue)
271
+ SerializedIssue.new(issue.id, issue.story_type, issue.name)
272
+ end
273
+
274
+ protected
214
275
  def project
215
- read
216
276
  @project ||= PivotalTracker::Project.find(@config['project_id'])
217
277
  end
218
278
 
219
- def me
220
- read
221
- @me ||= @config['me']
279
+ end
280
+
281
+
282
+ class JiraConfiguration < Configuration
283
+
284
+ def initialize(config)
285
+ super(config)
222
286
  end
223
287
 
224
- def global_config_path
225
- @global_config_path ||= File.expand_path('~')
288
+ def setup_api_client
289
+ require 'jira'
290
+ @client ||= JIRA::Client.new(
291
+ :username => username,
292
+ :password => @config[:password],
293
+ :site => @config[:site],
294
+ :context_path => '',
295
+ :auth_type => :basic,
296
+ )
226
297
  end
227
298
 
228
- def project_config_path
229
- @project_config_path ||= find_project_config
299
+ def client
300
+ @client
230
301
  end
231
302
 
303
+ def username
304
+ @username ||= @config[:username]
305
+ end
232
306
 
233
- private
307
+ def fetch_all_stories
308
+ client.Issue.jql("assignee=#{username} and status not in (done) and project = #{@config[:project_id]}")
309
+ end
234
310
 
235
- def find_project_config
236
- dirs = File.split(Dir.pwd)
237
- until dirs.empty? || File.exists?(File.join(dirs, '.pivotalrc'))
238
- dirs.pop
311
+ def find_story_by_id(key)
312
+ if key.to_i.to_s == key.to_s # no project_id in key
313
+ key = [@config[:project_id], key].join("-")
239
314
  end
240
- if dirs.empty? || File.join(dirs, '.pivotalrc')==global_config_path
315
+ serialize_issue(client.Issue.find(key))
316
+ rescue JIRA::HTTPError => e
317
+ if e.code.to_i == 404
241
318
  nil
242
319
  else
243
- File.join(dirs)
320
+ raise e
244
321
  end
245
322
  end
323
+
324
+ def serialize_issue(issue)
325
+ SerializedIssue.new(issue.key, issue.issuetype.name, issue.summary)
246
326
  end
327
+
247
328
  end
248
329
 
249
330
  class Error < StandardError
@@ -251,4 +332,26 @@ class GitStoryid
251
332
 
252
333
  class RefetchStories < StandardError
253
334
  end
335
+
336
+ TRACKER_CONFIG = {
337
+ pivotal: {
338
+ class: PivotalConfiguration,
339
+ options: {
340
+ :api_token => "Api token (https://www.pivotaltracker.com/profile)",
341
+ :me => "Your pivotal initials (e.g. BG)",
342
+ :project_id => "Project ID",
343
+ },
344
+ },
345
+ jira: {
346
+ class: JiraConfiguration,
347
+ options: {
348
+ :site => 'Site URL',
349
+ project_id: "Project ID",
350
+ :username => 'Username',
351
+ :password => 'Password',
352
+ }
353
+ }
354
+ }
355
+
356
+
254
357
  end
@@ -0,0 +1,108 @@
1
+
2
+ require "spec_helper"
3
+ require "fileutils"
4
+
5
+ describe GitStoryid do
6
+
7
+ let(:commands) { []}
8
+
9
+ def run(*args)
10
+ GitStoryid.run(*args)
11
+ end
12
+
13
+ def should_quit_with(expected)
14
+ actual = nil
15
+ GitStoryid.send(:define_method, :quit) do |message|
16
+ actual = message
17
+ end
18
+ yield
19
+ actual.should_not be_nil
20
+ actual.should == expected
21
+
22
+ end
23
+
24
+
25
+ describe "Pivotal" do
26
+
27
+ before(:each) do
28
+
29
+ GitStoryid::Configuration.stubs(:load_config_from).
30
+ returns(
31
+ "api_token" => "a2b4e",
32
+ "use_ssl" => false,
33
+ "me" => "BG",
34
+ "project_id" => "1234"
35
+ )
36
+ commands = self.commands
37
+ GitStoryid.send(:define_method, :execute) do |*args|
38
+ commands << args
39
+ ""
40
+ end
41
+ GitStoryid.any_instance.stubs(:ensure_changes_stashed!).returns(true)
42
+ GitStoryid.any_instance.stubs(:output).returns(true)
43
+
44
+ GitStoryid::Configuration.stubs(:project).returns(Hashie::Mash.new(
45
+ :initial_velocity => 10,
46
+ :labels => "bonobos,true&co,website",
47
+ :id => 135657,
48
+ :week_start_day => "Monday",
49
+ :use_https => false,
50
+ :iteration_length => 1,
51
+ :account => "Allan Grant",
52
+ :name => "Curebit Marketing",
53
+ :stories => PivotalTracker::Story,
54
+ :last_activity_at => DateTime.now,
55
+ :velocity_scheme => "Average of 3 iterations",
56
+ :current_iteration_number => 122,
57
+ :current_velocity => 19,
58
+ :point_scale => "0,1,2,3",
59
+ :first_iteration_start_time => DateTime.now
60
+ ))
61
+
62
+ GitStoryid::PivotalConfiguration.any_instance.stubs(:fetch_all_stories).returns([
63
+ Hashie::Mash.new(
64
+ :deadline => nil,
65
+ :labels => "paypal",
66
+ :accepted_at => nil,
67
+ :id => 44647731,
68
+ :jira_id => nil,
69
+ :estimate => 1,
70
+ :integration_id => nil,
71
+ :owned_by => "Bogdan Gusiev",
72
+ :name => "Strip Default paypal credentials",
73
+ :created_at => DateTime.now,
74
+ :story_type => "feature",
75
+ :other_id => nil,
76
+ :description => "",
77
+ :requested_by => "Dominic Coryell",
78
+ :url => "http://www.pivotaltracker.com/story/show/44647731",
79
+ :attachments => [],
80
+ :project_id => 135657,
81
+ :jira_url => nil,
82
+ :current_state => "finished"
83
+ ),
84
+ Hashie::Mash.new(
85
+ :deadline => nil,
86
+ :labels => "paypal",
87
+ :accepted_at => nil,
88
+ :id => 44647732,
89
+ :jira_id => nil,
90
+ :estimate => 1,
91
+ :integration_id => nil,
92
+ :owned_by => "Bogdan Gusiev",
93
+ :name => "Require pro paypal account for mass payments",
94
+ :created_at => DateTime.now,
95
+ :story_type => "feature",
96
+ :other_id => nil,
97
+ :description => "",
98
+ :requested_by => "Dominic Coryell",
99
+ :url => "http://www.pivotaltracker.com/story/show/44647732",
100
+ :attachments => [],
101
+ :project_id => 135657,
102
+ :jira_url => nil,
103
+ :current_state => "finished"
104
+ )
105
+ ])
106
+ end
107
+ end
108
+ end
@@ -9,26 +9,35 @@ describe GitStoryid do
9
9
  GitStoryid.run(*args)
10
10
  end
11
11
 
12
+ class ForceQuit < StandardError
13
+ end
14
+
12
15
  def should_quit_with(expected)
13
16
  actual = nil
14
17
  GitStoryid.send(:define_method, :quit) do |message|
15
18
  actual = message
19
+ raise ForceQuit
16
20
  end
17
21
  yield
22
+ true.should eq(false)
23
+ rescue ForceQuit
18
24
  actual.should_not be_nil
19
25
  actual.should == expected
20
26
 
21
27
  end
22
28
 
23
29
 
30
+ describe "Pivotal" do
31
+
24
32
  before(:each) do
25
-
26
- GitStoryid::Configuration.config = {
27
- "api_token" => "a2b4e",
28
- "use_ssl" => false,
29
- "me" => "BG",
30
- "project_id" => "1234"
31
- }
33
+
34
+ GitStoryid::Configuration.stubs(:load_config_from).
35
+ returns(
36
+ engine: "pivotal",
37
+ api_token: "a2b4e",
38
+ me: "BG",
39
+ project_id: "1234",
40
+ )
32
41
  commands = self.commands
33
42
  GitStoryid.send(:define_method, :execute) do |*args|
34
43
  commands << args
@@ -37,25 +46,7 @@ describe GitStoryid do
37
46
  GitStoryid.any_instance.stubs(:ensure_changes_stashed!).returns(true)
38
47
  GitStoryid.any_instance.stubs(:output).returns(true)
39
48
 
40
- GitStoryid::Configuration.stubs(:project).returns(Hashie::Mash.new(
41
- :initial_velocity => 10,
42
- :labels => "bonobos,true&co,website",
43
- :id => 135657,
44
- :week_start_day => "Monday",
45
- :use_https => false,
46
- :iteration_length => 1,
47
- :account => "Allan Grant",
48
- :name => "Curebit Marketing",
49
- :stories => PivotalTracker::Story,
50
- :last_activity_at => DateTime.now,
51
- :velocity_scheme => "Average of 3 iterations",
52
- :current_iteration_number => 122,
53
- :current_velocity => 19,
54
- :point_scale => "0,1,2,3",
55
- :first_iteration_start_time => DateTime.now
56
- ))
57
-
58
- GitStoryid.any_instance.stubs(:all_stories).returns([
49
+ GitStoryid::PivotalConfiguration.any_instance.stubs(:fetch_all_stories).returns([
59
50
  Hashie::Mash.new(
60
51
  :deadline => nil,
61
52
  :labels => "paypal",
@@ -147,6 +138,7 @@ EOI
147
138
  end
148
139
 
149
140
 
141
+ end
150
142
 
151
143
 
152
144
  end
@@ -3,6 +3,8 @@ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
3
  require 'rspec'
4
4
  require "webmock"
5
5
  require "hashie"
6
+ require "pivotal_tracker"
7
+ require 'jira-ruby'
6
8
  require 'git-storyid'
7
9
 
8
10
  # Requires supporting files with custom matchers and macros, etc,
@@ -13,5 +15,5 @@ WebMock.disable_net_connect!
13
15
 
14
16
  RSpec.configure do |config|
15
17
  config.mock_with :mocha
16
-
18
+
17
19
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: git-storyid
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.5
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bogdan Gusiev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-01-13 00:00:00.000000000 Z
11
+ date: 2017-01-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pivotal-tracker
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: jira-ruby
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: webmock
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -108,6 +122,34 @@ dependencies:
108
122
  - - ">="
109
123
  - !ruby/object:Gem::Version
110
124
  version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: pry-byebug
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: http_logger
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
111
153
  description: Helps include pivotal story id and description in commit
112
154
  email: agresso@gmail.com
113
155
  executables:
@@ -129,6 +171,7 @@ files:
129
171
  - git-storyid.gemspec
130
172
  - lib/git-storyid.rb
131
173
  - lib/git_storyid.rb
174
+ - spec/git_storyid/jira_spec.rb
132
175
  - spec/git_storyid_spec.rb
133
176
  - spec/spec_helper.rb
134
177
  homepage: http://github.com/bogdan/git-storyid
@@ -151,7 +194,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
151
194
  version: '0'
152
195
  requirements: []
153
196
  rubyforge_project:
154
- rubygems_version: 2.4.7
197
+ rubygems_version: 2.6.7
155
198
  signing_key:
156
199
  specification_version: 4
157
200
  summary: Attach commits to pivotal stories