trollolo 0.2.0 → 0.3.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: 561041c5f8420e41a174b2c3f54b493454b1a220
4
- data.tar.gz: fcdcb4abeab34f5e6e3b1b823851a5a1fd9d7081
2
+ SHA256:
3
+ metadata.gz: 39645441651332bd9aa763b5eea9827f46681b85569482dd8a5f69aae5a54f6f
4
+ data.tar.gz: 638a3a09670e1515faf53a02a8e8fc849ef46156c27509d4f8799a21c19cc25b
5
5
  SHA512:
6
- metadata.gz: 7322aef84f271b3cb8d457ffb6af4c9f7c46b302966e96403ca7f17753007602c31dd11d06ba739554fb8914b3e44017cefe5613ab72a2844a1e0e8bbdf6738a
7
- data.tar.gz: dd8f8af43466dd9663eee33df0fba9a8559c0ea26fcf6e40a81108a396c3177a5bf606e84a7ac0994cf01e93db8dd27dd39fe3a5fe32b2cca96b8de6e79d40a6
6
+ metadata.gz: 19fe728b12ab77109ad83310ab46e781be3bdf24c6388a5bf403b783043e327d7cbe6119b836c503995c4fe66db37cb5e2229c20969b95446e29d9fc6a9f6e97
7
+ data.tar.gz: 9983169a36878297fdbd4fc10bb46f4c97b030b24308a95abd96cd9ca6f013bbe5f73a55ededfa0a0fb7cb8a9b9deec5b1fdb6e7199e0d0ec87896d1c5f7a205
data/.gitignore CHANGED
@@ -2,3 +2,4 @@
2
2
  Gemfile.lock
3
3
  tmp
4
4
  coverage
5
+ .vscode
data/.rubocop.yml CHANGED
@@ -1,5 +1,9 @@
1
1
  inherit_from: .rubocop_todo.yml
2
2
 
3
+ # This probably rather should be EnforcedStyle: brackets
4
+ Style/WordArray:
5
+ Enabled: false
6
+
3
7
  #################### Metrics ###############################
4
8
 
5
9
  Metrics/AbcSize:
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
@@ -1,11 +1,12 @@
1
1
  language: ruby
2
2
  cache: bundler
3
3
  before_install:
4
- - gem --version
5
4
  - gem list bundler
6
5
  rvm:
7
6
  - "2.2.3"
8
7
  - "2.3.1"
8
+ - "2.4.3"
9
+ - "2.5.0"
9
10
  script:
10
11
  - 'bundle exec rubocop -D'
11
12
  - 'bundle exec rspec spec/unit'
data/CHANGELOG.md CHANGED
@@ -1,7 +1,10 @@
1
1
  # Trollolo Changelog
2
2
 
3
- ## Master (unreleased)
3
+ ## Version 0.3.0
4
4
 
5
+ * Support for Ruby >= 2.2, including Ruby 2.5
6
+ * Add support for swimlanes, used for cards which are not part of the normal
7
+ sprint.
5
8
 
6
9
  ## Version 0.2.0
7
10
 
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 please open pull requests.
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 rspec test:
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 'codeclimate-test-reporter', '>= 1.0.0'
7
- gem 'rspec', '~> 3.5'
6
+ gem 'awesome_print'
7
+ gem 'byebug'
8
8
  gem 'cli_tester'
9
- gem 'webmock'
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 'rubocop', '0.52.1'
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 2.2-2.4.1, but currently it doesn't work with 2.4.2. See [#139](https://github.com/openSUSE/trollolo/issues/139) for more information.
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
  ![Burndown example](https://raw.githubusercontent.com/openSUSE/trollolo/master/examples/burndown-26.png)
@@ -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
- if fast_lane_cards.total > 0
73
- base['fast_lane'] = {
74
- 'total' => fast_lane_cards.total,
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.keys.each do |name|
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']
data/lib/column.rb CHANGED
@@ -50,7 +50,7 @@ class Column
50
50
  end
51
51
 
52
52
  def committed_cards
53
- cards.select{|c| !c.extra? && !c.unplanned?}
53
+ cards.select{|c| !c.extra? && !c.unplanned? && !c.swimlane?}
54
54
  end
55
55
 
56
56
  def fast_lane_cards