git-storyid 0.3.2 → 0.5.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
- 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: []