git_story 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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