git-storyid 0.3.5 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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