westarete-tracker-tools 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.rspec +2 -0
- data/.rvmrc +1 -0
- data/Gemfile +30 -0
- data/Gemfile.lock +59 -0
- data/LICENSE.txt +20 -0
- data/README.md +190 -0
- data/Rakefile +79 -0
- data/VERSION +1 -0
- data/autotest/discover.rb +1 -0
- data/bin/backlog +47 -0
- data/bin/done +53 -0
- data/bin/finished +25 -0
- data/bin/validate +29 -0
- data/ci +21 -0
- data/lib/westarete-tracker-tools.rb +6 -0
- data/lib/westarete-tracker-tools/project.rb +69 -0
- data/lib/westarete-tracker-tools/story.rb +137 -0
- data/spec/fixtures/vcr/WestAreteTrackerTools_Project.yml +525 -0
- data/spec/fixtures/vcr/WestAreteTrackerTools_Story.yml +777 -0
- data/spec/helper.rb +17 -0
- data/spec/project_spec.rb +132 -0
- data/spec/story_spec.rb +408 -0
- data/spec/vcr_helper.rb +11 -0
- data/westarete-tracker-tools.gemspec +109 -0
- metadata +248 -0
data/.document
ADDED
data/.rspec
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm use 1.8.7@westarete-tracker-tools
|
data/Gemfile
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
source :rubygems
|
2
|
+
|
3
|
+
# Tools for creating a gem
|
4
|
+
gem 'jeweler', '1.5.2'
|
5
|
+
|
6
|
+
# API wrapper for Pivotal Tracker
|
7
|
+
gem 'pivotal-tracker', '0.3.0'
|
8
|
+
|
9
|
+
# Validations and relationships
|
10
|
+
gem 'activemodel', '3.0.3'
|
11
|
+
|
12
|
+
group :development do
|
13
|
+
# Test framework
|
14
|
+
gem 'rspec', '2.2.0'
|
15
|
+
|
16
|
+
# Produce rspec output in junit format for jenkins
|
17
|
+
gem 'ci_reporter', '1.6.4'
|
18
|
+
|
19
|
+
# Measure test coverage
|
20
|
+
gem 'rcov', '0.9.9'
|
21
|
+
|
22
|
+
# Automatically run tests as you code
|
23
|
+
gem 'autotest', '4.4.6'
|
24
|
+
|
25
|
+
# Record and play back API requests during tests
|
26
|
+
gem 'vcr', '1.4.0'
|
27
|
+
|
28
|
+
# Mock out API requests
|
29
|
+
gem 'fakeweb', '1.3.0'
|
30
|
+
end
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
ZenTest (4.4.2)
|
5
|
+
activemodel (3.0.3)
|
6
|
+
activesupport (= 3.0.3)
|
7
|
+
builder (~> 2.1.2)
|
8
|
+
i18n (~> 0.4)
|
9
|
+
activesupport (3.0.3)
|
10
|
+
autotest (4.4.6)
|
11
|
+
ZenTest (>= 4.4.1)
|
12
|
+
builder (2.1.2)
|
13
|
+
ci_reporter (1.6.4)
|
14
|
+
builder (>= 2.1.2)
|
15
|
+
diff-lcs (1.1.2)
|
16
|
+
fakeweb (1.3.0)
|
17
|
+
git (1.2.5)
|
18
|
+
happymapper (0.3.2)
|
19
|
+
libxml-ruby (~> 1.1.3)
|
20
|
+
i18n (0.5.0)
|
21
|
+
jeweler (1.5.2)
|
22
|
+
bundler (~> 1.0.0)
|
23
|
+
git (>= 1.2.5)
|
24
|
+
rake
|
25
|
+
libxml-ruby (1.1.4)
|
26
|
+
mime-types (1.16)
|
27
|
+
nokogiri (1.4.3.1)
|
28
|
+
pivotal-tracker (0.3.0)
|
29
|
+
builder
|
30
|
+
happymapper (>= 0.3.2)
|
31
|
+
nokogiri (~> 1.4.3.1)
|
32
|
+
rest-client (~> 1.6.0)
|
33
|
+
rake (0.8.7)
|
34
|
+
rcov (0.9.9)
|
35
|
+
rest-client (1.6.1)
|
36
|
+
mime-types (>= 1.16)
|
37
|
+
rspec (2.2.0)
|
38
|
+
rspec-core (~> 2.2)
|
39
|
+
rspec-expectations (~> 2.2)
|
40
|
+
rspec-mocks (~> 2.2)
|
41
|
+
rspec-core (2.4.0)
|
42
|
+
rspec-expectations (2.4.0)
|
43
|
+
diff-lcs (~> 1.1.2)
|
44
|
+
rspec-mocks (2.4.0)
|
45
|
+
vcr (1.4.0)
|
46
|
+
|
47
|
+
PLATFORMS
|
48
|
+
ruby
|
49
|
+
|
50
|
+
DEPENDENCIES
|
51
|
+
activemodel (= 3.0.3)
|
52
|
+
autotest (= 4.4.6)
|
53
|
+
ci_reporter (= 1.6.4)
|
54
|
+
fakeweb (= 1.3.0)
|
55
|
+
jeweler (= 1.5.2)
|
56
|
+
pivotal-tracker (= 0.3.0)
|
57
|
+
rcov (= 0.9.9)
|
58
|
+
rspec (= 2.2.0)
|
59
|
+
vcr (= 1.4.0)
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 West Arete Computing, Inc.
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,190 @@
|
|
1
|
+
# westarete-tracker-tools
|
2
|
+
|
3
|
+
This gem contains a set of tools and extensions that West Arete uses to report
|
4
|
+
on [Pivotal Tracker](https://www.pivotaltracker.com/) across all of its
|
5
|
+
projects.
|
6
|
+
|
7
|
+
## Goals
|
8
|
+
|
9
|
+
* Extract the set of stories that are available to work on across all active
|
10
|
+
projects
|
11
|
+
* Validate stories in the backlog to ensure that they meet our standards
|
12
|
+
* Report on completed iterations for billing and reporting purposes
|
13
|
+
* Wedge the following additional information into each feature:
|
14
|
+
* Risk
|
15
|
+
* Price
|
16
|
+
|
17
|
+
## Manifesto
|
18
|
+
|
19
|
+
This is an opinionated gem. It assumes that you are using Tracker the way that
|
20
|
+
West Arete is using it. That is to say:
|
21
|
+
|
22
|
+
* Stories are not available to be worked on until they are in the backlog
|
23
|
+
* Features are not allowed into the backlog until they have all of the
|
24
|
+
following attributes:
|
25
|
+
* A substantial description
|
26
|
+
* A point estimate
|
27
|
+
* A risk rating (see below)
|
28
|
+
* A price or cost estimate (see below)
|
29
|
+
* Stories should be requested by the project's stakeholder
|
30
|
+
* Acceptance of a story implies that it is ready to be invoiced
|
31
|
+
|
32
|
+
If these rules do not hold true for your organization, you may need to fork
|
33
|
+
this project and modify the behavior so that it better suits your needs.
|
34
|
+
|
35
|
+
### Risk
|
36
|
+
|
37
|
+
West Arete assigns an objective risk rating to each feature. This helps us to
|
38
|
+
achieve a balanced risk profile for each iteration for the sake of developer
|
39
|
+
productivity and happiness. It also gives valuable feedback to the managers
|
40
|
+
about how the feature should be priced, so that risk is apportioned fairly
|
41
|
+
between West Arete and the client.
|
42
|
+
|
43
|
+
Our ratings borrow from the rock climbing tradition of using movie ratings
|
44
|
+
to communicate risk. A climb that is rated PG is generally less dangerous than
|
45
|
+
one that is rated R. In the same way, we assign a risk rating to each feature:
|
46
|
+
|
47
|
+
* G: I have implemented something exactly like this recently.
|
48
|
+
* PG: I have implemented something quite similar to this.
|
49
|
+
* PG-13: I know how to do this, but it will involve a gem, library, or
|
50
|
+
technique that I haven't used before.
|
51
|
+
* R: I know how to do this, but I don't know exactly how long it will take; or
|
52
|
+
it involves an entirely new environment; or it involves adopting outsiders'
|
53
|
+
code.
|
54
|
+
* X: I'm not completely sure I will succeed at implementing this.
|
55
|
+
|
56
|
+
Risk ratings are only assigned to features. They are not assigned to bugs,
|
57
|
+
chores, or releases (although an average rating could probably be determined
|
58
|
+
for the latter).
|
59
|
+
|
60
|
+
There are a couple implicit ramifications of this system:
|
61
|
+
|
62
|
+
* Risk is dependent upon the person or team who will be implementing the
|
63
|
+
feature -- what is G for one person or team may be R for another.
|
64
|
+
* Risk is dependent upon the implementation. The decision to implement a
|
65
|
+
feature using a new gem will increase the risk to at least PG-13, even if it's
|
66
|
+
anticipated that it will be easier to accomplish (which may reduce the point
|
67
|
+
estimate).
|
68
|
+
|
69
|
+
Risk is encoded into a story in Tracker by enclosing it in square braces at
|
70
|
+
the beginning of the feature's title. For example:
|
71
|
+
|
72
|
+
[PG-13] Geolocation
|
73
|
+
|
74
|
+
### Price
|
75
|
+
|
76
|
+
West Arete generally prices its services per feature. Whenever possible, the
|
77
|
+
price is set as a fixed bid per story. However, when the risk for a feature is
|
78
|
+
too high, the feature is usually implemented at an hourly rate so that the
|
79
|
+
risk is shared by both West Arete and the Client.
|
80
|
+
|
81
|
+
With this library, prices are set in Tracker by having a manager comment on
|
82
|
+
the story with the estimated price. The library picks up on this by searching
|
83
|
+
the managers' comments for the words "cost" or "price" followed by a dollar
|
84
|
+
figure. The most recent managers' comment that sets a price wins.
|
85
|
+
|
86
|
+
## Setup
|
87
|
+
|
88
|
+
You'll need to create a `.pivotal_tracker_api_token` file in your home
|
89
|
+
directory. It should contain nothing but your API key from the bottom of [your
|
90
|
+
Tracker profile page](https://www.pivotaltracker.com/profile).
|
91
|
+
|
92
|
+
## Library
|
93
|
+
|
94
|
+
This gem provides a clean, high-level reporting interface to the [Pivotal
|
95
|
+
Tracker v3 API](https://www.pivotaltracker.com/help/api).
|
96
|
+
|
97
|
+
Under the covers, this gem uses the [pivotal-tracker
|
98
|
+
gem](https://github.com/jsmestad/pivotal-tracker) to do the actual
|
99
|
+
communication with the Pivotal API. We've encapsulated that gem's object model
|
100
|
+
to provide a higher level interface that adds our own custom functionality.
|
101
|
+
|
102
|
+
However, our interface is not a superset of the pivotal-tracker gem -- we've
|
103
|
+
only implemented the portions of the API that are useful to us.
|
104
|
+
|
105
|
+
The API documentation for this gem is here:
|
106
|
+
|
107
|
+
<http://rdoc.info/github/westarete/westarete-tracker-tools/master/frames>
|
108
|
+
|
109
|
+
## Executables
|
110
|
+
|
111
|
+
There are two command-line executables that are included with the gem. They
|
112
|
+
build upon the library to do some key reporting for us.
|
113
|
+
|
114
|
+
Both scripts presume that they're being run on Mac OS X, so that they can
|
115
|
+
easily write to the clipboard.
|
116
|
+
|
117
|
+
### backlog
|
118
|
+
|
119
|
+
This script collects all stories that are available to be worked on across
|
120
|
+
all projects.
|
121
|
+
|
122
|
+
Example usage:
|
123
|
+
|
124
|
+
bundle exec bin/backlog
|
125
|
+
|
126
|
+
The standard output reports progress and any story validation errors that are
|
127
|
+
encountered. A healthy backlog should have no errors. A link to each story
|
128
|
+
is provided.
|
129
|
+
|
130
|
+
After the script has completed successfully, a report of all the available
|
131
|
+
stories is copied to the clipboard and is ready to be pasted into a
|
132
|
+
spreadsheet.
|
133
|
+
|
134
|
+
### done
|
135
|
+
|
136
|
+
This script summarizes the accepted stories across all projects for a given
|
137
|
+
iteration.
|
138
|
+
|
139
|
+
It accepts a sole command line argument: an integer of zero or less, which
|
140
|
+
represents the iteration offset. An offset of zero means the current
|
141
|
+
iteration. An offset of -1 means the previous iteration. An offset of -2 means
|
142
|
+
two iterations ago, etc. If the script is run with no arguments, it reports on
|
143
|
+
the current iteration (an offset of 0).
|
144
|
+
|
145
|
+
Example usage:
|
146
|
+
|
147
|
+
bundle exec bin/done -2
|
148
|
+
|
149
|
+
This will gather all completed stories from two iterations ago. The standard
|
150
|
+
output will report on progress and any invalid stories that are encountered.
|
151
|
+
After completion, a summary of the stories will be left on the clipboard,
|
152
|
+
ready to be pasted into a spreadsheet.
|
153
|
+
|
154
|
+
### finished
|
155
|
+
|
156
|
+
This script looks for stories that are close to being done. They may be in a
|
157
|
+
state of "finished", "delivered", or "rejected". The team can run this
|
158
|
+
periodically to see which stories or stakeholders need a nudge to get a story
|
159
|
+
completed.
|
160
|
+
|
161
|
+
### validate
|
162
|
+
|
163
|
+
This script simply scrutinizes the backlog looking for stories that fail
|
164
|
+
validation. It reports any problems and then exits with a non-zero status if
|
165
|
+
any stories fail. It's designed to be run from a continuous integration
|
166
|
+
system.
|
167
|
+
|
168
|
+
## Contributing to westarete-tracker-tools
|
169
|
+
|
170
|
+
* Check out the latest master to make sure the feature hasn't been implemented
|
171
|
+
or the bug hasn't been fixed yet
|
172
|
+
* Check out the issue tracker to make sure someone already hasn't requested it
|
173
|
+
and/or contributed it
|
174
|
+
* Fork the project
|
175
|
+
* Start a feature/bugfix branch
|
176
|
+
* Commit and push until you are happy with your contribution
|
177
|
+
* Make sure to add tests for it. This is important so I don't break it in a
|
178
|
+
future version unintentionally.
|
179
|
+
* Please try not to mess with the Rakefile, version, or history. If you want
|
180
|
+
to have your own version, or is otherwise necessary, that is fine, but please
|
181
|
+
isolate to its own commit so I can cherry-pick around it.
|
182
|
+
|
183
|
+
This project follows the conventions of [Semantic
|
184
|
+
Versioning](http://semver.org/).
|
185
|
+
|
186
|
+
## Copyright
|
187
|
+
|
188
|
+
Copyright (c) 2011 West Arete Computing, Inc. See LICENSE.txt for
|
189
|
+
further details.
|
190
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
begin
|
4
|
+
Bundler.setup(:default, :development)
|
5
|
+
rescue Bundler::BundlerError => e
|
6
|
+
$stderr.puts e.message
|
7
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
+
exit e.status_code
|
9
|
+
end
|
10
|
+
require 'rake'
|
11
|
+
|
12
|
+
require 'jeweler'
|
13
|
+
Jeweler::Tasks.new do |gem|
|
14
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
15
|
+
gem.name = "westarete-tracker-tools"
|
16
|
+
gem.homepage = "http://github.com/westarete/westarete-tracker-tools"
|
17
|
+
gem.license = "MIT"
|
18
|
+
gem.summary = %Q{A set of tools and extensions that West Arete uses to report
|
19
|
+
on Pivotal Tracker.}
|
20
|
+
gem.description = %Q{
|
21
|
+
This gem contains a set of tools and extensions that West Arete uses to report
|
22
|
+
on Pivotal Tracker across all of its projects.
|
23
|
+
|
24
|
+
Goals:
|
25
|
+
|
26
|
+
* Extract the set of stories that are available to work on across all active
|
27
|
+
projects
|
28
|
+
* Validate stories in the backlog to ensure that they meet our standards
|
29
|
+
* Report on completed iterations for billing and reporting purposes
|
30
|
+
* Wedge the following additional information into each feature:
|
31
|
+
* Risk
|
32
|
+
* Price
|
33
|
+
}
|
34
|
+
gem.email = "scott@westarete.com"
|
35
|
+
gem.authors = ["Scott Woods"]
|
36
|
+
# Include your dependencies below. Runtime dependencies are required when using your gem,
|
37
|
+
# and development dependencies are only needed for development (ie running rake tasks, tests, etc)
|
38
|
+
# gem.add_runtime_dependency 'jabber4r', '> 0.1'
|
39
|
+
# gem.add_development_dependency 'rspec', '> 1.2.3'
|
40
|
+
end
|
41
|
+
Jeweler::RubygemsDotOrgTasks.new
|
42
|
+
|
43
|
+
# Produce test output that jenkins can read.
|
44
|
+
require 'ci/reporter/rake/rspec' # use this if you're using RSpec
|
45
|
+
# require 'ci/reporter/rake/cucumber' # use this if you're using Cucumber
|
46
|
+
# require 'ci/reporter/rake/test_unit' # use this if you're using Test::Unit
|
47
|
+
|
48
|
+
begin
|
49
|
+
require 'rspec/core/rake_task'
|
50
|
+
RSpec::Core::RakeTask.new('spec')
|
51
|
+
RSpec::Core::RakeTask.new('spec:rcov') do |t|
|
52
|
+
t.rcov = true
|
53
|
+
t.rcov_opts = %w{ --exclude spec --exclude gems }
|
54
|
+
end
|
55
|
+
task :default => :spec
|
56
|
+
rescue LoadError
|
57
|
+
puts "Could not find rspec gem. RSpec tasks will not be available."
|
58
|
+
end
|
59
|
+
|
60
|
+
begin
|
61
|
+
require 'rcov/rcovtask'
|
62
|
+
Rcov::RcovTask.new do |test|
|
63
|
+
test.libs << 'spec'
|
64
|
+
test.pattern = 'spec/**/*_spec.rb'
|
65
|
+
test.verbose = true
|
66
|
+
end
|
67
|
+
rescue LoadError
|
68
|
+
puts "Could not find rcov gem. Coverage tasks will not be available."
|
69
|
+
end
|
70
|
+
|
71
|
+
require 'rake/rdoctask'
|
72
|
+
Rake::RDocTask.new do |rdoc|
|
73
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
74
|
+
|
75
|
+
rdoc.rdoc_dir = 'rdoc'
|
76
|
+
rdoc.title = "westarete-tracker-tools #{version}"
|
77
|
+
rdoc.rdoc_files.include('README*')
|
78
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
79
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.3.0
|
@@ -0,0 +1 @@
|
|
1
|
+
Autotest.add_discovery { "rspec2" }
|
data/bin/backlog
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Extract all stories across all backlogs of all projects into a format
|
4
|
+
# that's ready to be pasted into a spreadsheet. Also report on any validation
|
5
|
+
# errors that are encountered.
|
6
|
+
|
7
|
+
require 'rubygems'
|
8
|
+
require 'bundler/setup'
|
9
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
10
|
+
require 'westarete-tracker-tools'
|
11
|
+
|
12
|
+
include WestAreteTrackerTools
|
13
|
+
|
14
|
+
number_of_problems = 0
|
15
|
+
IO.popen('pbcopy', 'w') do |clipboard|
|
16
|
+
Project.all.each do |project|
|
17
|
+
puts "- #{project.name}"
|
18
|
+
project.backlog.each do |story|
|
19
|
+
if ! story.valid?
|
20
|
+
puts " - Invalid Story"
|
21
|
+
puts " story_type: #{story.story_type}"
|
22
|
+
puts " name: \"#{story.name}\""
|
23
|
+
puts " url: #{story.url}"
|
24
|
+
puts " errors:"
|
25
|
+
story.errors.full_messages.each do |error|
|
26
|
+
puts " - #{error}"
|
27
|
+
end
|
28
|
+
number_of_problems += 1
|
29
|
+
end
|
30
|
+
clipboard.puts [
|
31
|
+
nil, # week starting
|
32
|
+
project.name,
|
33
|
+
story.story_type,
|
34
|
+
story.points,
|
35
|
+
story.risk,
|
36
|
+
nil, # deliverable type
|
37
|
+
story.name,
|
38
|
+
nil, # fixed / hourly
|
39
|
+
story.price,
|
40
|
+
story.url
|
41
|
+
].join("\t")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
puts "\nDone."
|
46
|
+
puts "The master backlog has been copied to your clipboard and is ready to be pasted into a spreadsheet."
|
47
|
+
exit number_of_problems
|