trollolo 0.2.0 → 0.3.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 +5 -5
- data/.gitignore +1 -0
- data/.rubocop.yml +4 -0
- data/.rubocop_todo.yml +3 -28
- data/.travis.yml +2 -1
- data/CHANGELOG.md +4 -1
- data/CONTRIBUTING.md +17 -3
- data/Gemfile +8 -8
- data/README.md +40 -2
- data/lib/burndown_chart.rb +9 -0
- data/lib/burndown_data.rb +80 -7
- data/lib/card.rb +17 -1
- data/lib/cli.rb +1 -1
- data/lib/column.rb +1 -1
- data/lib/scrum/creator.rb +1 -1
- data/lib/scrum_board.rb +12 -1
- data/lib/settings.rb +5 -3
- data/lib/version.rb +1 -1
- data/spec/data/burndown-data-with-doing-columns.yaml +32 -0
- data/spec/data/burndown-data-with-swimlanes.yaml +32 -0
- data/spec/data/burndown-data-with-todo-columns.yaml +35 -0
- data/spec/integration/create_burndown_spec.rb +2 -2
- data/spec/unit/board_mock_spec.rb +96 -0
- data/spec/unit/burndown_chart_spec.rb +15 -0
- data/spec/unit/burndown_data_spec.rb +174 -115
- data/spec/unit/card_spec.rb +111 -0
- data/spec/unit/cli_spec.rb +2 -0
- data/spec/unit/scrum_board_spec.rb +31 -0
- data/spec/unit/settings_spec.rb +0 -1
- data/spec/unit/support/board_mock.rb +63 -0
- data/spec/unit/trello_wrapper_spec.rb +15 -12
- data/trollolo.gemspec +3 -3
- metadata +11 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 39645441651332bd9aa763b5eea9827f46681b85569482dd8a5f69aae5a54f6f
|
4
|
+
data.tar.gz: 638a3a09670e1515faf53a02a8e8fc849ef46156c27509d4f8799a21c19cc25b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 19fe728b12ab77109ad83310ab46e781be3bdf24c6388a5bf403b783043e327d7cbe6119b836c503995c4fe66db37cb5e2229c20969b95446e29d9fc6a9f6e97
|
7
|
+
data.tar.gz: 9983169a36878297fdbd4fc10bb46f4c97b030b24308a95abd96cd9ca6f013bbe5f73a55ededfa0a0fb7cb8a9b9deec5b1fdb6e7199e0d0ec87896d1c5f7a205
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
data/.rubocop_todo.yml
CHANGED
@@ -6,14 +6,6 @@
|
|
6
6
|
# Note that changes in the inspected code, or installation of new
|
7
7
|
# versions of RuboCop, may require this file to be generated again.
|
8
8
|
|
9
|
-
# Offense count: 7
|
10
|
-
# Cop supports --auto-correct.
|
11
|
-
# Configuration parameters: Include, TreatCommentsAsGroupSeparators.
|
12
|
-
# Include: **/*.gemfile, **/Gemfile, **/gems.rb
|
13
|
-
Bundler/OrderedGems:
|
14
|
-
Exclude:
|
15
|
-
- 'Gemfile'
|
16
|
-
|
17
9
|
# Offense count: 1
|
18
10
|
# Cop supports --auto-correct.
|
19
11
|
# Configuration parameters: Include, TreatCommentsAsGroupSeparators.
|
@@ -29,15 +21,6 @@ Gemspec/RequiredRubyVersion:
|
|
29
21
|
Exclude:
|
30
22
|
- 'trollolo.gemspec'
|
31
23
|
|
32
|
-
# Offense count: 8
|
33
|
-
# Cop supports --auto-correct.
|
34
|
-
# Configuration parameters: EnforcedStyle.
|
35
|
-
# SupportedStyles: leading, trailing
|
36
|
-
Layout/DotPosition:
|
37
|
-
Exclude:
|
38
|
-
- 'spec/integration/create_burndown_spec.rb'
|
39
|
-
- 'spec/unit/trello_wrapper_spec.rb'
|
40
|
-
|
41
24
|
# Offense count: 1
|
42
25
|
# Cop supports --auto-correct.
|
43
26
|
Layout/EmptyLineAfterMagicComment:
|
@@ -158,6 +141,9 @@ Layout/MultilineMethodCallIndentation:
|
|
158
141
|
Exclude:
|
159
142
|
- 'lib/burndown_chart.rb'
|
160
143
|
- 'spec/unit/trello_wrapper_spec.rb'
|
144
|
+
- 'spec/unit/board_mock_spec.rb' # Indendation is used to express structure of board
|
145
|
+
- 'spec/unit/burndown_data_spec.rb' # Indendation is used to express structure of board
|
146
|
+
- 'spec/unit/scrum_board_spec.rb' # Indendation is used to express structure of board
|
161
147
|
|
162
148
|
# Offense count: 2
|
163
149
|
# Cop supports --auto-correct.
|
@@ -308,14 +294,6 @@ Naming/UncommunicativeMethodArgName:
|
|
308
294
|
- 'lib/scrum/sprint_board.rb'
|
309
295
|
- 'lib/scrum/sprint_planning_board.rb'
|
310
296
|
|
311
|
-
# Offense count: 2
|
312
|
-
# Cop supports --auto-correct.
|
313
|
-
# Configuration parameters: AutoCorrect.
|
314
|
-
Performance/HashEachMethods:
|
315
|
-
Exclude:
|
316
|
-
- 'lib/cli.rb'
|
317
|
-
- 'lib/scrum/creator.rb'
|
318
|
-
|
319
297
|
# Offense count: 1
|
320
298
|
# Cop supports --auto-correct.
|
321
299
|
Security/YAMLLoad:
|
@@ -416,6 +394,3 @@ Style/PercentLiteralDelimiters:
|
|
416
394
|
# Cop supports --auto-correct.
|
417
395
|
# Configuration parameters: EnforcedStyle, AllowInnerSlashes.
|
418
396
|
# SupportedStyles: slashes, percent_r, mixed
|
419
|
-
Style/RegexpLiteral:
|
420
|
-
Exclude:
|
421
|
-
- 'trollolo.gemspec'
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
data/CONTRIBUTING.md
CHANGED
@@ -10,7 +10,7 @@ To discuss anything please [contact Cornelius](mailto:cschum@suse.de).
|
|
10
10
|
|
11
11
|
## Contribute code
|
12
12
|
|
13
|
-
To contribute code
|
13
|
+
To contribute code fork the repository and open pull requests with your changes.
|
14
14
|
|
15
15
|
Ensure that rspec and rubocop pass locally before sending your PR and always that you add new changes.
|
16
16
|
|
@@ -18,9 +18,9 @@ If your changes include important new features or bug fixes please add them to t
|
|
18
18
|
|
19
19
|
### To run rspec test
|
20
20
|
|
21
|
-
To run all the
|
21
|
+
To run all the unit tests:
|
22
22
|
|
23
|
-
`bundle exec rspec`
|
23
|
+
`bundle exec rspec spec/unit`
|
24
24
|
|
25
25
|
To run all the test in one spec file, for example `spec/unit/burndown_chart_spec.rb`:
|
26
26
|
|
@@ -30,8 +30,22 @@ To only run the test in the line 415 of the file:
|
|
30
30
|
|
31
31
|
`bundle exec rspec spec/unit/burndown_chart_spec.rb:415`
|
32
32
|
|
33
|
+
### To try your changes
|
34
|
+
|
35
|
+
Build the gem:
|
36
|
+
|
37
|
+
`bundle exec rake gem:build`
|
38
|
+
|
39
|
+
Install the gem:
|
40
|
+
|
41
|
+
`gem install trollolo-<version>.gem`
|
42
|
+
|
33
43
|
### To run rubocop
|
34
44
|
|
35
45
|
To run Rubocop displaying cop names in offense messages:
|
36
46
|
|
37
47
|
`bundle exec rubocop -D`
|
48
|
+
|
49
|
+
## Code of Conduct
|
50
|
+
|
51
|
+
Trollolo is part of the openSUSE project. We follow all the [openSUSE Guiding Principles](https://en.opensuse.org/openSUSE:Guiding_principles)!
|
data/Gemfile
CHANGED
@@ -3,17 +3,17 @@ source 'https://rubygems.org'
|
|
3
3
|
gemspec
|
4
4
|
|
5
5
|
group :test do
|
6
|
-
gem '
|
7
|
-
gem '
|
6
|
+
gem 'awesome_print'
|
7
|
+
gem 'byebug'
|
8
8
|
gem 'cli_tester'
|
9
|
-
gem '
|
10
|
-
gem 'vcr'
|
9
|
+
gem 'codeclimate-test-reporter', '>= 1.0.0'
|
11
10
|
gem 'given_filesystem'
|
12
|
-
gem 'byebug'
|
13
|
-
gem 'awesome_print'
|
14
11
|
gem 'pry'
|
15
|
-
gem 'ronn', '>=0.7.3'
|
16
12
|
gem 'rake'
|
17
|
-
gem '
|
13
|
+
gem 'ronn', '>=0.7.3'
|
14
|
+
gem 'rspec', '~> 3.5'
|
18
15
|
gem 'rspec-mocks'
|
16
|
+
gem 'rubocop', '0.52.1'
|
17
|
+
gem 'vcr'
|
18
|
+
gem 'webmock'
|
19
19
|
end
|
data/README.md
CHANGED
@@ -21,7 +21,7 @@ which demonstrates the expected structure.
|
|
21
21
|
|
22
22
|
## Installation
|
23
23
|
|
24
|
-
You need to have Ruby install. Trollolo works with Ruby
|
24
|
+
You need to have Ruby install. Trollolo works with Ruby >= 2.2.
|
25
25
|
|
26
26
|
You can install Trollolo as gem with `gem install trollolo`.
|
27
27
|
|
@@ -139,7 +139,6 @@ The specified `URL` can contain placeholders which will be replaced:
|
|
139
139
|
:board => Board ID
|
140
140
|
|
141
141
|
|
142
|
-
|
143
142
|
To generate the actual burndown chart, go to the working directory and call:
|
144
143
|
|
145
144
|
trollolo plot SPRINT_NUMBER
|
@@ -156,6 +155,45 @@ Trello board.
|
|
156
155
|
Some more info can be found in the command line help with `trollolo help` and
|
157
156
|
`trollolo help burndown`.
|
158
157
|
|
158
|
+
### Swimlanes
|
159
|
+
|
160
|
+
You can define swimlanes to exclude certain cards from the normal burndown
|
161
|
+
data. This can be useful when you track work of multiple projects on the same
|
162
|
+
board and you don't want to apply the full Scrum framework to all of them. An
|
163
|
+
example would be a side project which you limit to one card in process.
|
164
|
+
|
165
|
+
Swimlanes are defined by putting a label with the name of the swimlane on all
|
166
|
+
cards which belong to this swimlane. It does not matter in which column they
|
167
|
+
are. To make Trollolo aware of the swimlane, you need to add an entry in the
|
168
|
+
meta section of the burndown YAML such as:
|
169
|
+
|
170
|
+
meta:
|
171
|
+
swimlanes:
|
172
|
+
- My Side Project
|
173
|
+
|
174
|
+
This lets Trollolo exclude all cards which have the label with the name
|
175
|
+
`My Side Project` from the burndown chart.
|
176
|
+
|
177
|
+
The data for swimlane cards is collected separately in the burndown YAML
|
178
|
+
separated in `todo`, `doing`, and `done` values. This can be used to generate
|
179
|
+
statistics for the swimlanes. Trollolo currently only writes the raw data
|
180
|
+
but doesn't support any statistics such as generating graphs.
|
181
|
+
|
182
|
+
### Column names
|
183
|
+
|
184
|
+
Trollolo by default looks for columns named such as `Sprint Backlog`, `Doing`,
|
185
|
+
or `Done`. If you need more or other names you can configure that in the burndown
|
186
|
+
YAML. Here is an example:
|
187
|
+
|
188
|
+
meta:
|
189
|
+
todo_columns:
|
190
|
+
- Main Backlog
|
191
|
+
- Swimlane Backlog
|
192
|
+
doing_columns:
|
193
|
+
- Doing
|
194
|
+
- Review
|
195
|
+
- QA
|
196
|
+
|
159
197
|
### Example
|
160
198
|
|
161
199
|

|
data/lib/burndown_chart.rb
CHANGED
@@ -84,8 +84,17 @@ class BurndownChart
|
|
84
84
|
|
85
85
|
def read_data(filename)
|
86
86
|
@data = YAML.load_file filename
|
87
|
+
|
88
|
+
todo_columns = @data['meta']['todo_columns']
|
89
|
+
@settings.todo_columns = todo_columns if todo_columns
|
90
|
+
|
91
|
+
doing_columns = @data['meta']['doing_columns']
|
92
|
+
@settings.doing_columns = doing_columns if doing_columns
|
93
|
+
|
87
94
|
not_done_columns = @data['meta']['not_done_columns']
|
88
95
|
@settings.not_done_columns = not_done_columns if not_done_columns
|
96
|
+
|
97
|
+
@settings.swimlanes = @data['meta']['swimlanes'] || []
|
89
98
|
end
|
90
99
|
|
91
100
|
def write_data(filename)
|
data/lib/burndown_data.rb
CHANGED
@@ -33,9 +33,31 @@ class BurndownData
|
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
|
+
class SwimlaneResult
|
37
|
+
attr_accessor :todo, :doing, :done
|
38
|
+
|
39
|
+
def add_todo(story_points)
|
40
|
+
@todo += story_points
|
41
|
+
end
|
42
|
+
|
43
|
+
def add_doing(story_points)
|
44
|
+
@doing += story_points
|
45
|
+
end
|
46
|
+
|
47
|
+
def add_done(story_points)
|
48
|
+
@done += story_points
|
49
|
+
end
|
50
|
+
|
51
|
+
def initialize
|
52
|
+
@todo = 0
|
53
|
+
@doing = 0
|
54
|
+
@done = 0
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
36
58
|
attr_accessor :story_points, :tasks, :extra_story_points, :extra_tasks,
|
37
59
|
:unplanned_story_points, :unplanned_tasks,
|
38
|
-
:board_id, :fast_lane_cards, :date_time
|
60
|
+
:board_id, :fast_lane_cards, :date_time, :swimlanes
|
39
61
|
attr_reader :meta
|
40
62
|
|
41
63
|
def initialize(settings)
|
@@ -48,6 +70,11 @@ class BurndownData
|
|
48
70
|
@unplanned_tasks = Result.new
|
49
71
|
@fast_lane_cards = Result.new
|
50
72
|
@date_time = Time.now
|
73
|
+
|
74
|
+
@swimlanes = {}
|
75
|
+
settings.swimlanes.each do |swimlane|
|
76
|
+
@swimlanes[swimlane] = SwimlaneResult.new
|
77
|
+
end
|
51
78
|
end
|
52
79
|
|
53
80
|
def to_hash
|
@@ -69,12 +96,9 @@ class BurndownData
|
|
69
96
|
'done' => extra_tasks.done
|
70
97
|
}
|
71
98
|
}
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
'open' => fast_lane_cards.open
|
76
|
-
}
|
77
|
-
end
|
99
|
+
|
100
|
+
base['fast_lane'] = fast_lane_to_hash if fast_lane_cards.total > 0
|
101
|
+
|
78
102
|
if unplanned_story_points.total > 0
|
79
103
|
base['unplanned_story_points'] = {
|
80
104
|
'total' => unplanned_story_points.total,
|
@@ -85,9 +109,31 @@ class BurndownData
|
|
85
109
|
'open' => unplanned_tasks.open
|
86
110
|
}
|
87
111
|
end
|
112
|
+
|
113
|
+
base['swimlanes'] = swimlanes_to_hash unless swimlanes.empty?
|
114
|
+
|
88
115
|
base
|
89
116
|
end
|
90
117
|
|
118
|
+
def fast_lane_to_hash
|
119
|
+
{
|
120
|
+
'total' => fast_lane_cards.total,
|
121
|
+
'open' => fast_lane_cards.open
|
122
|
+
}
|
123
|
+
end
|
124
|
+
|
125
|
+
def swimlanes_to_hash
|
126
|
+
swimlanes_element = {}
|
127
|
+
swimlanes.each do |name, swimlane_result|
|
128
|
+
swimlanes_element[name] = {
|
129
|
+
'todo' => swimlane_result.todo,
|
130
|
+
'doing' => swimlane_result.doing,
|
131
|
+
'done' => swimlane_result.done
|
132
|
+
}
|
133
|
+
end
|
134
|
+
swimlanes_element
|
135
|
+
end
|
136
|
+
|
91
137
|
def trello
|
92
138
|
@trello ||= TrelloWrapper.new(@settings)
|
93
139
|
end
|
@@ -113,6 +159,33 @@ class BurndownData
|
|
113
159
|
@fast_lane_cards.done = board.done_fast_lane_cards_count
|
114
160
|
@fast_lane_cards.open = board.open_fast_lane_cards_count
|
115
161
|
@date_time = DateTime.now
|
162
|
+
|
163
|
+
fetch_swimlanes
|
164
|
+
end
|
165
|
+
|
166
|
+
def fetch_swimlanes
|
167
|
+
@settings.swimlanes.each do |swimlane|
|
168
|
+
board.todo_columns.each do |column|
|
169
|
+
column.cards.each do |card|
|
170
|
+
@swimlanes[swimlane].add_todo(card.story_points) if card.label?(swimlane)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
board.doing_columns.each do |column|
|
175
|
+
column.cards.each do |card|
|
176
|
+
@swimlanes[swimlane].add_doing(card.story_points) if card.label?(swimlane)
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
board.done_column.cards.each do |card|
|
181
|
+
@swimlanes[swimlane].add_done(card.story_points) if card.label?(swimlane)
|
182
|
+
end
|
183
|
+
board.accepted_columns.each do |column|
|
184
|
+
column.cards.each do |card|
|
185
|
+
@swimlanes[swimlane].add_done(card.story_points) if card.label?(swimlane)
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
116
189
|
end
|
117
190
|
|
118
191
|
private
|
data/lib/card.rb
CHANGED
@@ -52,10 +52,17 @@ class Card
|
|
52
52
|
end
|
53
53
|
|
54
54
|
def card_labels
|
55
|
-
@card_data['labels']
|
55
|
+
@card_data['labels'] || []
|
56
|
+
end
|
57
|
+
|
58
|
+
def label?(label_name)
|
59
|
+
card_labels.any? do |label|
|
60
|
+
label['name'].include?(label_name)
|
61
|
+
end
|
56
62
|
end
|
57
63
|
|
58
64
|
def checklists
|
65
|
+
return [] unless @card_data['checklists']
|
59
66
|
@card_data['checklists'].map do |checklist|
|
60
67
|
Checklist.new(checklist)
|
61
68
|
end
|
@@ -84,6 +91,15 @@ class Card
|
|
84
91
|
end
|
85
92
|
end
|
86
93
|
|
94
|
+
def swimlane?
|
95
|
+
card_labels.each do |label|
|
96
|
+
@settings.swimlanes.each do |swimlane|
|
97
|
+
return true if label['name'].include?(swimlane)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
false
|
101
|
+
end
|
102
|
+
|
87
103
|
def meta_card?
|
88
104
|
name =~ SPRINT_NUMBER_REGEX
|
89
105
|
end
|
data/lib/cli.rb
CHANGED
@@ -134,7 +134,7 @@ EOT
|
|
134
134
|
def burndowns
|
135
135
|
process_global_options options
|
136
136
|
board_list = YAML.load_file(options['board-list'])
|
137
|
-
board_list.
|
137
|
+
board_list.each_key do |name|
|
138
138
|
raise 'invalid character in team name' if name =~ /[^[:alnum:]. _]/ # sanitize
|
139
139
|
board = board_list[name]
|
140
140
|
if options['output']
|