git-storyid 0.3.2 → 0.5.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
- SHA1:
3
- metadata.gz: ea0c96c0cc6afc52210c376d0c46ed4e58ce27f4
4
- data.tar.gz: 958cd9d0871e7a71dd45ae14f3585bcd6c3236d1
2
+ SHA256:
3
+ metadata.gz: bc54e25bc8d5baee1ad92cd40a911de1bc2182eb1b3295ada65d6590b8d0c081
4
+ data.tar.gz: d0c1b93785bd05d31bcafa88fe4224bbf159d195231f2778d867c904e6b87511
5
5
  SHA512:
6
- metadata.gz: 330859df25358888f7f78bf48b003d9abe3003ac291e7c9bbd8ed2c5a0a9eabc2227b8a5c05dd3ba07c828f5fca8d0155fb22ef40b1f037533b59528f28ae098
7
- data.tar.gz: 49ddd88705a4466a6facf5bf9c48e9bf94e38c1269fe8b5dd5d4466212f7ce26044a4997a0e2368fed1604d02a78fcda0d5b1cc5975fe2a7342250e4c7e5f2d5
6
+ metadata.gz: bce50d473b0d9ac819576ce6d502c86b5c699ca5d567189e06f80cae4d0d81a9973f532e47b103f4b5c5ce450544ee6851cf4c9907d43f089f0b85ca6b4e89be
7
+ data.tar.gz: cf3213b24382d62e1398e6b26021aed52a253970c6b440de3f181e9267d7583372235cd474c102772bc49362cd1e49a911901c9a6faece991c521d51fea3fcfe
data/Gemfile CHANGED
@@ -1,11 +1,15 @@
1
1
  source "http://rubygems.org"
2
2
 
3
- gem "pivotal-tracker"
3
+ gem "tracker_api"
4
+ gem "jira-ruby"
5
+
4
6
  group :development do
5
7
  gem "webmock"
6
8
  gem "debugger", :platform => "ruby_19"
7
9
  gem "mocha"
8
10
  gem "rspec"
9
- gem "jeweler"
11
+ gem "juwelier", github: 'flajann2/juwelier'
10
12
  gem "hashie"
13
+ gem "pry-byebug", require: false
14
+ gem "http_logger"
11
15
  end
@@ -1,59 +1,158 @@
1
+ GIT
2
+ remote: git://github.com/flajann2/juwelier.git
3
+ revision: de59d5a2ddea00c1f18957ab62129c1c141acce1
4
+ specs:
5
+ juwelier (2.4.9)
6
+ builder
7
+ bundler
8
+ git
9
+ github_api
10
+ highline
11
+ kamelcase (~> 0)
12
+ nokogiri
13
+ psych
14
+ rake
15
+ rdoc
16
+ semver2
17
+
1
18
  GEM
2
19
  remote: http://rubygems.org/
3
20
  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)
21
+ activesupport (6.0.3.2)
22
+ concurrent-ruby (~> 1.0, >= 1.0.2)
23
+ i18n (>= 0.7, < 2)
24
+ minitest (~> 5.1)
25
+ tzinfo (~> 1.1)
26
+ zeitwerk (~> 2.2, >= 2.2.2)
27
+ addressable (2.7.0)
28
+ public_suffix (>= 2.0.2, < 5.0)
29
+ atlassian-jwt (0.2.0)
30
+ jwt (~> 2.1.0)
31
+ axiom-types (0.1.1)
32
+ descendants_tracker (~> 0.0.4)
33
+ ice_nine (~> 0.11.0)
34
+ thread_safe (~> 0.3, >= 0.3.1)
35
+ builder (3.2.4)
36
+ byebug (11.1.3)
37
+ coderay (1.1.3)
38
+ coercible (1.0.0)
39
+ descendants_tracker (~> 0.0.1)
40
+ columnize (0.9.0)
41
+ concurrent-ruby (1.1.7)
42
+ crack (0.4.3)
43
+ safe_yaml (~> 1.0.0)
44
+ debugger (1.6.8)
9
45
  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)
22
- git (>= 1.2.5)
23
- rake
24
- 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)
30
- metaclass (~> 0.0.1)
31
- nokogiri (1.5.5)
32
- pivotal-tracker (0.5.4)
33
- builder
34
- builder
35
- happymapper (>= 0.3.2)
36
- happymapper (>= 0.3.2)
37
- nokogiri (>= 1.4.3)
38
- nokogiri (~> 1.4)
39
- rest-client (~> 1.6.0)
40
- rest-client (~> 1.6.0)
41
- rake (10.2.2)
42
- rdoc (4.1.1)
43
- json (~> 1.4)
44
- rest-client (1.6.7)
45
- mime-types (>= 1.16)
46
- rspec (2.13.0)
47
- rspec-core (~> 2.13.0)
48
- rspec-expectations (~> 2.13.0)
49
- rspec-mocks (~> 2.13.0)
50
- rspec-core (2.13.0)
51
- rspec-expectations (2.13.0)
52
- diff-lcs (>= 1.1.3, < 2.0)
53
- rspec-mocks (2.13.0)
54
- webmock (1.8.7)
55
- addressable (>= 2.2.7)
56
- crack (>= 0.1.7)
46
+ debugger-linecache (~> 1.2.0)
47
+ debugger-ruby_core_source (~> 1.3.5)
48
+ debugger-linecache (1.2.0)
49
+ debugger-ruby_core_source (1.3.8)
50
+ declarative (0.0.20)
51
+ declarative-option (0.1.0)
52
+ descendants_tracker (0.0.4)
53
+ thread_safe (~> 0.3, >= 0.3.1)
54
+ diff-lcs (1.4.4)
55
+ equalizer (0.0.11)
56
+ excon (0.76.0)
57
+ faraday (1.0.1)
58
+ multipart-post (>= 1.2, < 3)
59
+ faraday_middleware (1.0.0)
60
+ faraday (~> 1.0)
61
+ git (1.7.0)
62
+ rchardet (~> 1.8)
63
+ github_api (0.19.0)
64
+ addressable (~> 2.4)
65
+ descendants_tracker (~> 0.0.4)
66
+ faraday (>= 0.8, < 2)
67
+ hashie (~> 3.5, >= 3.5.2)
68
+ oauth2 (~> 1.0)
69
+ hashdiff (1.0.1)
70
+ hashie (3.6.0)
71
+ highline (2.0.3)
72
+ http_logger (0.6.0)
73
+ i18n (1.8.5)
74
+ concurrent-ruby (~> 1.0)
75
+ ice_nine (0.11.2)
76
+ jira-ruby (2.1.3)
77
+ activesupport
78
+ atlassian-jwt
79
+ multipart-post
80
+ oauth (~> 0.5, >= 0.5.0)
81
+ jwt (2.1.0)
82
+ kamelcase (0.0.2)
83
+ semver2 (~> 3)
84
+ method_source (1.0.0)
85
+ mimemagic (0.3.5)
86
+ mini_portile2 (2.4.0)
87
+ minitest (5.14.1)
88
+ mocha (1.11.2)
89
+ multi_json (1.15.0)
90
+ multi_xml (0.6.0)
91
+ multipart-post (2.1.1)
92
+ nokogiri (1.10.10)
93
+ mini_portile2 (~> 2.4.0)
94
+ oauth (0.5.4)
95
+ oauth2 (1.4.4)
96
+ faraday (>= 0.8, < 2.0)
97
+ jwt (>= 1.0, < 3.0)
98
+ multi_json (~> 1.3)
99
+ multi_xml (~> 0.5)
100
+ rack (>= 1.2, < 3)
101
+ pry (0.13.1)
102
+ coderay (~> 1.1)
103
+ method_source (~> 1.0)
104
+ pry-byebug (3.9.0)
105
+ byebug (~> 11.0)
106
+ pry (~> 0.13.0)
107
+ psych (3.2.0)
108
+ public_suffix (4.0.5)
109
+ rack (2.2.3)
110
+ rake (13.0.1)
111
+ rchardet (1.8.0)
112
+ rdoc (6.2.1)
113
+ representable (3.0.4)
114
+ declarative (< 0.1.0)
115
+ declarative-option (< 0.2.0)
116
+ uber (< 0.2.0)
117
+ rspec (3.9.0)
118
+ rspec-core (~> 3.9.0)
119
+ rspec-expectations (~> 3.9.0)
120
+ rspec-mocks (~> 3.9.0)
121
+ rspec-core (3.9.2)
122
+ rspec-support (~> 3.9.3)
123
+ rspec-expectations (3.9.2)
124
+ diff-lcs (>= 1.2.0, < 2.0)
125
+ rspec-support (~> 3.9.0)
126
+ rspec-mocks (3.9.1)
127
+ diff-lcs (>= 1.2.0, < 2.0)
128
+ rspec-support (~> 3.9.0)
129
+ rspec-support (3.9.3)
130
+ safe_yaml (1.0.5)
131
+ semver2 (3.4.2)
132
+ thread_safe (0.3.6)
133
+ tracker_api (1.11.0)
134
+ addressable
135
+ equalizer
136
+ excon
137
+ faraday
138
+ faraday_middleware
139
+ mimemagic
140
+ multi_json
141
+ representable
142
+ virtus
143
+ tzinfo (1.2.7)
144
+ thread_safe (~> 0.1)
145
+ uber (0.1.0)
146
+ virtus (1.0.5)
147
+ axiom-types (~> 0.1)
148
+ coercible (~> 1.0)
149
+ descendants_tracker (~> 0.0, >= 0.0.3)
150
+ equalizer (~> 0.0, >= 0.0.9)
151
+ webmock (3.8.3)
152
+ addressable (>= 2.3.6)
153
+ crack (>= 0.3.2)
154
+ hashdiff (>= 0.4.0, < 2.0.0)
155
+ zeitwerk (2.4.0)
57
156
 
58
157
  PLATFORMS
59
158
  ruby
@@ -61,8 +160,14 @@ PLATFORMS
61
160
  DEPENDENCIES
62
161
  debugger
63
162
  hashie
64
- jeweler
163
+ http_logger
164
+ jira-ruby
165
+ juwelier!
65
166
  mocha
66
- pivotal-tracker
167
+ pry-byebug
67
168
  rspec
169
+ tracker_api
68
170
  webmock
171
+
172
+ BUNDLED WITH
173
+ 1.17.3
data/README.md CHANGED
@@ -47,3 +47,11 @@ Feature: Tag campaign insertion points and
47
47
  campaigns with an identifier,
48
48
  so only campaigns with matching identifier will get shown
49
49
  ```
50
+
51
+ ## Supported options
52
+
53
+ ```
54
+ -m, --message [MESSAGE] Add addional MESSAGE to comit
55
+ -f, --finish Specify that this commit finishes a story or fixes a bug
56
+ -d, --deliver Specify that this commit delivers a story or a bug
57
+ ```
data/Rakefile CHANGED
@@ -11,8 +11,8 @@ rescue Bundler::BundlerError => e
11
11
  end
12
12
  require 'rake'
13
13
 
14
- require 'jeweler'
15
- Jeweler::Tasks.new do |gem|
14
+ require 'juwelier'
15
+ Juwelier::Tasks.new do |gem|
16
16
  # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
17
  gem.name = "git-storyid"
18
18
  gem.executables = ['git-storyid']
@@ -24,7 +24,7 @@ Jeweler::Tasks.new do |gem|
24
24
  gem.authors = ["Bogdan Gusiev"]
25
25
  # dependencies defined in Gemfile
26
26
  end
27
- Jeweler::RubygemsDotOrgTasks.new
27
+ Juwelier::RubygemsDotOrgTasks.new
28
28
 
29
29
  require 'rspec/core'
30
30
  require 'rspec/core/rake_task'
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.2
1
+ 0.5.0
@@ -1,20 +1,20 @@
1
- # Generated by jeweler
1
+ # Generated by juwelier
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
3
+ # Instead, edit Juwelier::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
- # stub: git-storyid 0.3.2 ruby lib
5
+ # stub: git-storyid 0.5.0 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
- s.name = "git-storyid"
9
- s.version = "0.3.2"
8
+ s.name = "git-storyid".freeze
9
+ s.version = "0.5.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 = "2014-04-14"
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 = "2020-08-31"
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.2.2"
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 = "3.0.8".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<tracker_api>.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<juwelier>.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<tracker_api>.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<juwelier>.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<tracker_api>.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<juwelier>.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,54 +10,71 @@ 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"
17
27
  opts.on("-m", "--message [MESSAGE]", "Add addional MESSAGE to comit") do |custom_message|
18
28
  @custom_message = custom_message
19
29
  end
30
+ opts.on("-f", "--finish", "Specify that this commit finishes a story or fixes a bug") do
31
+ @finish_stories = true
32
+ end
33
+ opts.on("-d", "--deliver", "Specify that this commit delivers a story or a bug") do
34
+ @deliver_stories = true
35
+ end
20
36
  end
21
37
  parser.parse!(arguments)
22
38
 
23
39
  unless arguments.empty?
24
40
  @stories = arguments.map do |argument|
25
- Configuration.project.stories.find(argument)
41
+ @tracker.find_story_by_id(argument)
26
42
  end
27
43
  end
28
44
  end
29
45
 
30
- def all_stories
31
- @all_stories ||= Configuration.project.stories.all(
32
- :owner => Configuration.me,
33
- :state => %w(started finished delivered),
34
- :limit => 30
35
- )
36
- end
37
-
38
46
  def readline_stories_if_not_present
39
47
  if !@stories || @stories.empty?
40
48
  quit_if_no_stories
41
49
  output stories_menu
42
50
  @stories = readline_story_ids.map do |index|
43
- all_stories[index - 1] || (quit("Story index #{index} not found."))
51
+ fetch_story(index) || quit("Story #{index} was not found.")
44
52
  end
45
53
  end
54
+ rescue RefetchStories
55
+ @tracker.reset
56
+ @stories = nil
57
+ readline_stories_if_not_present
46
58
  end
47
59
 
48
- def output(message)
49
- 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
50
67
  end
51
68
 
52
69
  def quit_if_no_stories
53
- if all_stories.empty?
70
+ if @tracker.all_stories.empty?
54
71
  quit "No stories started and owned by you."
55
72
  end
56
73
  end
57
74
 
58
75
  def stories_menu
59
76
  result = ""
60
- all_stories.each_with_index do |story, index|
77
+ @tracker.all_stories.each_with_index do |story, index|
61
78
  result << "[#{index + 1}] #{story.name}\n"
62
79
  end
63
80
  result << "\n"
@@ -65,15 +82,22 @@ class GitStoryid
65
82
  end
66
83
 
67
84
  def readline_story_ids
68
- ids = readline.split(/\s*,\s*/).reject do |string|
85
+ input = readline
86
+ if input =~ /\A\s*re?f?r?e?s?h?\s*\z/
87
+ raise RefetchStories
88
+ end
89
+ ids = input.split(/\s*,\s*/).reject do |string|
69
90
  string.empty?
70
91
  end
71
- quit("Cancelling.") if ids.empty?
72
- ids.map {|id| id.to_i }
92
+ if ids.empty?
93
+ quit("Cancelling.")
94
+ else
95
+ ids
96
+ end
73
97
  end
74
98
 
75
99
  def readline
76
- Readline.readline("Indexes(csv): ", true)
100
+ Readline.readline("Indexes: ", true)
77
101
  end
78
102
 
79
103
  def quit(message)
@@ -92,15 +116,25 @@ class GitStoryid
92
116
  end
93
117
 
94
118
  def build_commit_message
95
- message = ("[#{@stories.map { |s| "\##{s.id}"}.join(", ")}]").rjust 12
96
- message += ' '
119
+ message = @stories.map do |story|
120
+ "#{finish_story_prefix(story)}##{story.id}"
121
+ end.join(", ")
122
+ message = "[#{message}] "
97
123
  if @custom_message && !@custom_message.empty?
98
124
  message += @custom_message.to_s + "\n\n"
99
125
  end
100
- message += @stories.map {|s| "#{s.story_type.capitalize}: " + s.name.strip}.join("\n\n")
126
+ message += @stories.map do |story|
127
+ "#{story.type.capitalize}: " + story.name.strip
128
+ end.join("\n\n")
101
129
  message
102
130
  end
103
131
 
132
+ def finish_story_prefix(story)
133
+ return "Delivers " if @deliver_stories
134
+ return "" unless @finish_stories
135
+ story.type == "bug" ? "Fixes " : "Finishes "
136
+ end
137
+
104
138
  def execute(*args)
105
139
  Open3.popen3(*args) {|i, o| return o.read }
106
140
  end
@@ -111,113 +145,213 @@ class GitStoryid
111
145
  end
112
146
  end
113
147
 
148
+ class Configuration
114
149
 
115
- module Configuration
116
- class << self
117
-
118
- def config=(config)
119
- @config = config
120
- end
121
-
122
- def read
123
- return if @loaded
150
+ def self.build
124
151
  load_config
125
152
  ensure_full_config
126
- setup_api_client
127
- @loaded = true
153
+ TRACKER_CONFIG[engine][:class].new(@config)
128
154
  end
129
155
 
130
- def load_config
131
- @config ||= {}
132
- @config.merge!(load_config_from(global_config_path))
133
- @project_config = load_config_from(project_config_path)
134
- @config.merge!(@project_config)
135
- end
156
+ class << self
136
157
 
137
- def setup_api_client
138
- PivotalTracker::Client.token = @config['api_token']
139
- PivotalTracker::Client.use_ssl = @config['use_ssl'] ? @config['use_ssl'] : false
140
- end
141
-
142
- def ensure_full_config
143
- changed = false
144
- {
145
- "api_token" => "Api token (https://www.pivotaltracker.com/profile)",
146
- "use_ssl" => "Use SSL (y/n)",
147
- "me" => "Your pivotal initials (e.g. BG)",
148
- "project_id" => "Project ID"
149
- }.each do |key, label|
150
- if @config[key].nil?
151
- changed = true
152
- value = Readline.readline("#{label}: ", true)
153
- @project_config[key] = format_config_value(value)
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)
154
179
  end
180
+ output "Writing config to #{project_config_path}"
155
181
  end
156
- if changed
157
- File.open("./.pivotalrc", "w") do |file|
158
- file.write YAML.dump(@project_config)
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)
159
192
  end
160
- @config.merge!(@project_config)
161
- #output "Writing config to .pivotalrc"
162
193
  end
163
- end
164
194
 
165
- def format_config_value(value)
166
- case value
167
- when "y"
168
- true
169
- when "n"
170
- false
171
- else
172
- value
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
173
217
  end
174
218
  end
175
219
 
176
- def load_config_from(path)
177
- return {} unless path
178
- file = File.join path,'.pivotalrc'
179
- if File.exists?(file)
180
- YAML.load(File.read(file)) || {}
181
- else
182
- {}
220
+ def initialize(config)
221
+ @config = config
222
+ setup_api_client
223
+ end
224
+
225
+ def all_stories
226
+ @all_stories ||= fetch_all_stories.map do |story|
227
+ serialize_issue(story)
183
228
  end
184
229
  end
185
230
 
186
- def project
187
- read
188
- @project ||= PivotalTracker::Project.find(@config['project_id'])
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
+
248
+ def setup_api_client
249
+ require "tracker_api"
250
+ @client ||= TrackerApi::Client.new(token: @config[:api_token])
189
251
  end
190
252
 
191
253
  def me
192
- read
193
254
  @me ||= @config['me']
194
255
  end
195
256
 
196
- def global_config_path
197
- @global_config_path ||= File.expand_path('~')
257
+ def fetch_all_stories
258
+ project.stories(
259
+ filter: "mywork:#{me} state:started,finished,delivered",
260
+ # :owner => me,
261
+ # :with_state => %w(started finished delivered),
262
+ :limit => 30
263
+ )
198
264
  end
199
265
 
200
- def project_config_path
201
- @project_config_path ||= find_project_config
266
+ def find_story_by_id(id)
267
+ serialize_issue(project.story(id))
202
268
  end
203
269
 
270
+ def serialize_issue(issue)
271
+ SerializedIssue.new(issue.id, issue.story_type, issue.name)
272
+ end
204
273
 
205
- private
274
+ protected
275
+ def project
276
+ @project ||= @client.project(@config['project_id'])
277
+ end
206
278
 
207
- def find_project_config
208
- dirs = File.split(Dir.pwd)
209
- until dirs.empty? || File.exists?(File.join(dirs, '.pivotalrc'))
210
- dirs.pop
279
+ end
280
+
281
+
282
+ class JiraConfiguration < Configuration
283
+
284
+ def initialize(config)
285
+ super(config)
286
+ end
287
+
288
+ def setup_api_client
289
+ require 'jira-ruby'
290
+ @client ||= JIRA::Client.new(
291
+ :username => username,
292
+ :password => @config[:password],
293
+ :site => @config[:site],
294
+ :context_path => '',
295
+ :auth_type => :basic,
296
+ )
297
+ end
298
+
299
+ def client
300
+ @client
301
+ end
302
+
303
+ def username
304
+ @username ||= @config[:username]
305
+ end
306
+
307
+ def fetch_all_stories
308
+ client.Issue.jql("assignee=#{username} and status not in (done) and project = #{@config[:project_id]}")
309
+ end
310
+
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("-")
211
314
  end
212
- 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
213
318
  nil
214
319
  else
215
- File.join(dirs)
320
+ raise e
216
321
  end
217
322
  end
323
+
324
+ def serialize_issue(issue)
325
+ SerializedIssue.new(issue.key, issue.issuetype.name, issue.summary)
218
326
  end
327
+
219
328
  end
220
329
 
221
330
  class Error < StandardError
222
331
  end
332
+
333
+ class RefetchStories < StandardError
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
+
223
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",
@@ -102,15 +93,11 @@ describe GitStoryid do
102
93
  end
103
94
 
104
95
  context "when stories exists" do
105
-
106
- before(:each) do
107
-
108
- GitStoryid.any_instance.stubs(:readline).returns('1')
109
- end
110
96
 
111
97
  it "should commit changes" do
98
+ GitStoryid.any_instance.stubs(:readline).returns('1')
112
99
  run("-m", 'Hello world')
113
- commands.should include(["git", "commit", "-m", " [#44647731] Hello world\n\nFeature: Strip Default paypal credentials"])
100
+ commands.should include(["git", "commit", "-m", "[#44647731] Hello world\n\nFeature: Strip Default paypal credentials"])
114
101
  end
115
102
 
116
103
  it "should render stories menu correctly" do
@@ -120,6 +107,27 @@ describe GitStoryid do
120
107
 
121
108
  EOI
122
109
  end
110
+
111
+ it "should commit to multiple stories" do
112
+ GitStoryid.any_instance.stubs(:readline).returns('1,2')
113
+ run("-m", 'Hello world')
114
+ commands.should include(
115
+ ["git", "commit", "-m",
116
+ "[#44647731, #44647732] Hello world\n\nFeature: Strip Default paypal credentials\n\nFeature: Require pro paypal account for mass payments"]
117
+ )
118
+ end
119
+
120
+ it "should support finishing" do
121
+ GitStoryid.any_instance.stubs(:readline).returns('1')
122
+ run('-f')
123
+ commands.should include(["git", "commit", "-m", "[Finishes #44647731] Feature: Strip Default paypal credentials"])
124
+ end
125
+
126
+ it "should support delivering" do
127
+ GitStoryid.any_instance.stubs(:readline).returns('1')
128
+ run('-d')
129
+ commands.should include(["git", "commit", "-m", "[Delivers #44647731] Feature: Strip Default paypal credentials"])
130
+ end
123
131
  end
124
132
 
125
133
  it "should quit if no stories specified" do
@@ -130,6 +138,7 @@ EOI
130
138
  end
131
139
 
132
140
 
141
+ end
133
142
 
134
143
 
135
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 "tracker_api"
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,17 +1,31 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: git-storyid
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bogdan Gusiev
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-04-14 00:00:00.000000000 Z
11
+ date: 2020-08-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: pivotal-tracker
14
+ name: tracker_api
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: jira-ruby
15
29
  requirement: !ruby/object:Gem::Requirement
16
30
  requirements:
17
31
  - - ">="
@@ -81,7 +95,7 @@ dependencies:
81
95
  - !ruby/object:Gem::Version
82
96
  version: '0'
83
97
  - !ruby/object:Gem::Dependency
84
- name: jeweler
98
+ name: juwelier
85
99
  requirement: !ruby/object:Gem::Requirement
86
100
  requirements:
87
101
  - - ">="
@@ -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,13 +171,14 @@ 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
135
178
  licenses:
136
179
  - MIT
137
180
  metadata: {}
138
- post_install_message:
181
+ post_install_message:
139
182
  rdoc_options: []
140
183
  require_paths:
141
184
  - lib
@@ -150,9 +193,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
150
193
  - !ruby/object:Gem::Version
151
194
  version: '0'
152
195
  requirements: []
153
- rubyforge_project:
154
- rubygems_version: 2.2.2
155
- signing_key:
196
+ rubygems_version: 3.0.8
197
+ signing_key:
156
198
  specification_version: 4
157
199
  summary: Attach commits to pivotal stories
158
200
  test_files: []