git_story 0.2.1 → 0.2.2

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.
@@ -0,0 +1,4 @@
1
+ **0.2.1** 28/05/2012 a43e15ffde884810d8769a9706b2b37df10ab463
2
+
3
+ - Multiple projects supported
4
+ - Auto-project discovery
@@ -3,6 +3,7 @@ require_relative "git_story/version"
3
3
  require_relative 'manual_git_commit_lister'
4
4
  require_relative 'split_and_match_processor'
5
5
  require_relative 'tracker_fetched_mapper'
6
+ require_relative 'typhoeus_tracker_connector'
6
7
  require_relative 'puts_renderer'
7
8
 
8
9
  module GitStory
@@ -15,11 +16,16 @@ module GitStory
15
16
  commit_state_factory.list(since, until_commit)
16
17
  end
17
18
 
18
- def commit_state_factory
19
+ def commit_state_factory()
19
20
  renderer = PutsRenderer.new
20
- state_mapper = TrackerFetchedMapper.new(renderer)
21
+ tracker_connector = TyphoeusTrackerConnector.new(tracker_project_ids, ENV['TRACKER_TOKEN'])
22
+ state_mapper = TrackerFetchedMapper.new(renderer, tracker_connector)
21
23
  commit_processor = SplitAndMatchProcessor.new(state_mapper)
22
24
  ManualGitCommitLister.new(commit_processor)
23
25
  end
24
26
 
27
+ def tracker_project_ids
28
+ (ENV['TRACKER_PROJECT_ID'] || '').split(",")
29
+ end
30
+
25
31
  end
@@ -1,3 +1,3 @@
1
1
  module GitStory
2
- VERSION = "0.2.1"
2
+ VERSION = "0.2.2"
3
3
  end
@@ -1,8 +1,8 @@
1
1
  class PutsRenderer
2
- def render(commit_story_state)
3
- commit_story_state.each do |commit, story_state|
4
- unless story_state['state'] == :accepted
5
- puts "#{commit} ##{story_state['story']} #{story_state['state']}"
2
+ def render(commit_story_state_project)
3
+ commit_story_state_project.each do |commit, ssp|
4
+ unless ssp['state'] == :accepted
5
+ puts "#{commit} ##{ssp['story']} #{ssp['state']} from #{ssp['project']}"
6
6
  end
7
7
  end
8
8
  end
@@ -1,71 +1,20 @@
1
1
  class TrackerFetchedMapper
2
2
 
3
- def initialize(renderer)
3
+ def initialize(renderer, tracker_connector)
4
4
  @renderer = renderer
5
+ @tracker = tracker_connector
5
6
  end
6
7
 
7
8
  def execute(story_commit)
8
- @renderer.render(map(story_commit))
9
+ map = map(story_commit)
10
+ @renderer.render(map)
9
11
  end
10
12
 
11
13
  def map(story_commit)
12
14
  {}.tap do |h|
13
- fetch(story_commit.keys).each do |story, state|
14
- h[story_commit[story]] = {'story' => story, 'state' => state}
15
+ @tracker.details_for(story_commit.keys).each do |story, project_state|
16
+ h[story_commit[story]] = {'story' => story, 'state' => project_state[1], 'project' => project_state[0]}
15
17
  end
16
18
  end
17
19
  end
18
-
19
- def fetch(stories)
20
- require 'rubygems'
21
- require 'net/http'
22
- require 'uri'
23
- require 'nokogiri'
24
- require 'typhoeus'
25
-
26
- hydra = Typhoeus::Hydra.new
27
-
28
- if ENV['TRACKER_PROJECT_ID']
29
- projects = ENV['TRACKER_PROJECT_ID'].split(",")
30
- else
31
- request = Typhoeus::Request.new(
32
- "http://www.pivotaltracker.com/services/v3/projects",
33
- headers: {'X-TrackerToken' => ENV['TRACKER_TOKEN']})
34
- request.on_complete do |response|
35
- doc = Nokogiri::XML(response.body)
36
-
37
- doc.xpath('//projects/project').map do |e|
38
- e.xpath('id').text.to_i
39
- end
40
- end
41
- hydra.queue request
42
- hydra.run
43
- projects = request.handled_response
44
- end
45
- stories_qs = stories.join(',')
46
-
47
- requests = []
48
- projects.each do |project_id|
49
- request = Typhoeus::Request.new(
50
- "http://www.pivotaltracker.com/services/v3/projects/#{project_id}/stories?filter=id:#{stories_qs}&includedone:true",
51
- headers: {'X-TrackerToken' => ENV['TRACKER_TOKEN']})
52
-
53
- request.on_complete do |response|
54
- doc = Nokogiri::XML(response.body)
55
-
56
- {}.tap do |h|
57
- doc.xpath('//stories/story').map do |e|
58
- h[e.xpath('id').text] = e.xpath('current_state').text.to_sym
59
- end
60
- end
61
- end
62
-
63
- requests << request
64
- hydra.queue request
65
- end
66
- hydra.run
67
-
68
- requests.inject({}){|acc, r| acc.merge(r.handled_response) }
69
- end
70
-
71
20
  end
@@ -0,0 +1,58 @@
1
+ require 'nokogiri'
2
+ require 'typhoeus'
3
+
4
+ class TyphoeusTrackerConnector
5
+
6
+ def initialize(project_ids = [], tracker_token)
7
+ @hydra = Typhoeus::Hydra.new
8
+ @project_ids = project_ids
9
+ @token = tracker_token
10
+ end
11
+
12
+ def details_for(stories)
13
+ stories_qs = stories.join(',')
14
+ requests = []
15
+ projects.each do |id, name|
16
+ request = Typhoeus::Request.new(
17
+ "http://www.pivotaltracker.com/services/v3/projects/#{id}/stories?filter=id:#{stories_qs}&includedone:true",
18
+ headers: {'X-TrackerToken' => @token})
19
+
20
+ request.on_complete do |response|
21
+ doc = Nokogiri::XML(response.body)
22
+
23
+ {}.tap do |h|
24
+ doc.xpath('//stories/story').map do |e|
25
+ h[e.xpath('id').text] = [name, e.xpath('current_state').text.to_sym]
26
+ end
27
+ end
28
+ end
29
+
30
+ requests << request
31
+ @hydra.queue request
32
+ end
33
+ @hydra.run
34
+
35
+ requests.inject({}) { |acc, r| acc.merge(r.handled_response) }
36
+ end
37
+
38
+ private
39
+ def projects
40
+ request = Typhoeus::Request.new("http://www.pivotaltracker.com/services/v3/projects", headers: {'X-TrackerToken' => @token})
41
+ request.on_complete do |response|
42
+ doc = Nokogiri::XML(response.body)
43
+
44
+ {}.tap do |h|
45
+ doc.xpath('//projects/project').map do |e|
46
+ h[e.xpath('id').text.to_i] = e.xpath('name').text
47
+ end
48
+ end
49
+ end
50
+ @hydra.queue request
51
+ @hydra.run
52
+
53
+ all_projects = request.handled_response
54
+ all_projects.select { |k,_| @project_ids.include?(k.to_s) } unless @project_ids.empty?
55
+ all_projects
56
+ end
57
+
58
+ end
@@ -10,6 +10,7 @@ describe GitStory do
10
10
  let(:commits) { %w(8670b5ee48d9ea26a91b22f6eeee2234098b3a08 5257d758a95d37441e65d0b5198cbc9dae8cd2cf 70c9112ddf9f02e6680797f490e418d95a3836ed 13351e6dfc28e05cc4c13ea039654b95c62185a0) }
11
11
  let(:stories) { %w(29981485 29521391 29977427 29977409) }
12
12
  let(:states) { %w(accepted rejected finished started).each(&:to_sym) }
13
+ let(:project_names) { %w(proj_a proj_b proj_a proj_c) }
13
14
 
14
15
  def set_up_parameters
15
16
  ENV['TRACKER_TOKEN'] = 'fake tracker token'
@@ -26,7 +27,7 @@ raw_git_commit
26
27
  end
27
28
 
28
29
  def stub_network
29
- TrackerFetchedMapper.any_instance.stub(:fetch).with(stories).and_return(Hash[stories.zip(states)])
30
+ TyphoeusTrackerConnector.any_instance.stub(:details_for).with(stories).and_return(Hash[stories.zip(project_names.zip(states))])
30
31
  end
31
32
 
32
33
  it "run through CommitLister to Renderer" do
@@ -34,8 +35,8 @@ raw_git_commit
34
35
  stub_git
35
36
  stub_network
36
37
  render_input = {}.tap do |h|
37
- commits.zip(stories).zip(states).map(&:flatten).each do |css|
38
- h[css[0]] = {'story' => css[1], 'state' => css[2]}
38
+ commits.zip(stories).zip(states).zip(project_names).map(&:flatten).each do |cssp|
39
+ h[cssp[0]] = {'story' => cssp[1], 'state' => cssp[2], 'project' => cssp[3]}
39
40
  end
40
41
  end
41
42
  PutsRenderer.any_instance.should_receive(:render).with(render_input)
@@ -3,10 +3,9 @@ require_relative '../lib/tracker_fetched_mapper'
3
3
  describe TrackerFetchedMapper do
4
4
 
5
5
  let(:renderer) { mock('renderer') }
6
+ let(:tracker_connector) { mock('tracker_connector') }
6
7
 
7
- subject { TrackerFetchedMapper.new(renderer) }
8
-
9
- it { should respond_to :fetch }
8
+ subject { TrackerFetchedMapper.new(renderer, tracker_connector) }
10
9
 
11
10
  describe "#execute" do
12
11
  it "calls #map and passes result to Renderer" do
@@ -22,18 +21,18 @@ describe TrackerFetchedMapper do
22
21
 
23
22
  describe '#map' do
24
23
  it "maps { story_id => commit } to { commit => { story => story_id, state => state_symbol } }" do
25
- subject.should_receive(:fetch).with(['123', '234']).and_return({ '123' => :accepted, '234' => :rejected })
24
+ tracker_connector.stub(:details_for).with(['123', '234']).and_return({ '123' => ['proj_a', :accepted], '234' => ['proj_b', :rejected] })
26
25
  subject.map({ '123' => 'x', '234' => 'y' }).should ==
27
26
  {
28
- 'x' => { 'story' => '123', 'state' => :accepted },
29
- 'y' => { 'story' => '234', 'state' => :rejected }
27
+ 'x' => { 'story' => '123', 'state' => :accepted, 'project' => 'proj_a' },
28
+ 'y' => { 'story' => '234', 'state' => :rejected, 'project' => 'proj_b' }
30
29
  }
31
30
  end
32
31
 
33
32
  it "ignores commit that corresponding story is not returned from #fetch" do
34
- subject.should_receive(:fetch).with(['123', '234']).and_return({ '234' => :rejected })
33
+ tracker_connector.should_receive(:details_for).with(['123', '234']).and_return({ '234' => ['proj_b', :rejected] })
35
34
  subject.map({ '123' => 'x', '234' => 'y' }).should ==
36
- { 'y' => {'story' => '234', 'state' => :rejected } }
35
+ { 'y' => {'story' => '234', 'state' => :rejected, 'project' => 'proj_b' } }
37
36
  end
38
37
  end
39
38
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: git_story
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-05-28 00:00:00.000000000 Z
12
+ date: 2012-05-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
@@ -71,6 +71,7 @@ extra_rdoc_files: []
71
71
  files:
72
72
  - .gitignore
73
73
  - .travis.yml
74
+ - CHANGELOG.md
74
75
  - Gemfile
75
76
  - LICENSE
76
77
  - README.md
@@ -83,6 +84,7 @@ files:
83
84
  - lib/puts_renderer.rb
84
85
  - lib/split_and_match_processor.rb
85
86
  - lib/tracker_fetched_mapper.rb
87
+ - lib/typhoeus_tracker_connector.rb
86
88
  - spec/git_story_spec.rb
87
89
  - spec/split_and_match_processor_spec.rb
88
90
  - spec/tracker_fetched_state_spec.rb