trollolo 0.0.3

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,64 @@
1
+ # Copyright (c) 2013-2014 SUSE LLC
2
+ #
3
+ # This program is free software; you can redistribute it and/or
4
+ # modify it under the terms of version 3 of the GNU General Public License as
5
+ # published by the Free Software Foundation.
6
+ #
7
+ # This program is distributed in the hope that it will be useful,
8
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
+ # GNU General Public License for more details.
11
+ #
12
+ # You should have received a copy of the GNU General Public License
13
+ # along with this program; if not, contact SUSE LLC.
14
+ #
15
+ # To contact SUSE about this file by physical or electronic mail,
16
+ # you may find current contact information at www.suse.com
17
+
18
+ class Card
19
+
20
+ attr_accessor :sp, :tasks, :tasks_done
21
+
22
+ def self.name_to_points(card_name)
23
+ card_name =~ /^\(([\d.]+)\)/
24
+ return nil if $1.nil?
25
+ $1.to_f
26
+ end
27
+
28
+ def initialize
29
+ @sp = nil
30
+ @extra = false
31
+ end
32
+
33
+ def has_sp?
34
+ @sp != nil
35
+ end
36
+
37
+ def extra?
38
+ @extra
39
+ end
40
+
41
+ def set_extra
42
+ @extra = true
43
+ end
44
+
45
+ def self.parse json
46
+ card = Card.new
47
+
48
+ title = json["name"]
49
+ card.sp = name_to_points(title)
50
+
51
+ labels = json["labels"]
52
+ labels.each do |label|
53
+ if label["name"] == "Under waterline"
54
+ card.set_extra
55
+ end
56
+ end
57
+
58
+ card.tasks = json["badges"]["checkItems"]
59
+ card.tasks_done = json["badges"]["checkItemsChecked"]
60
+
61
+ card
62
+ end
63
+
64
+ end
@@ -0,0 +1,251 @@
1
+ # Copyright (c) 2013-2014 SUSE LLC
2
+ #
3
+ # This program is free software; you can redistribute it and/or
4
+ # modify it under the terms of version 3 of the GNU General Public License as
5
+ # published by the Free Software Foundation.
6
+ #
7
+ # This program is distributed in the hope that it will be useful,
8
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
+ # GNU General Public License for more details.
11
+ #
12
+ # You should have received a copy of the GNU General Public License
13
+ # along with this program; if not, contact SUSE LLC.
14
+ #
15
+ # To contact SUSE about this file by physical or electronic mail,
16
+ # you may find current contact information at www.suse.com
17
+
18
+ class Cli < Thor
19
+
20
+ default_task :global
21
+
22
+ class_option :version, :type => :boolean, :desc => "Show version"
23
+ class_option :verbose, :type => :boolean, :desc => "Verbose mode"
24
+ class_option :raw, :type => :boolean, :desc => "Raw mode"
25
+ class_option "board-id", :type => :string, :desc => "id of Trello board"
26
+
27
+ def self.settings= s
28
+ @@settings = s
29
+ end
30
+
31
+ desc "global", "Global options", :hide => true
32
+ def global
33
+ if options[:version]
34
+ puts "Trollolo: #{@@settings.version}"
35
+ else
36
+ Cli.help shell
37
+ end
38
+ end
39
+
40
+ desc "get-lists", "Get lists"
41
+ option "board-id", :desc => "Id of Trello board", :required => true
42
+ def get_lists
43
+ process_global_options options
44
+ require_trello_credentials
45
+
46
+ trello = Trello.new(board_id: options["board-id"], developer_public_key: @@settings.developer_public_key, member_token: @@settings.member_token)
47
+ lists = trello.lists
48
+
49
+ if @@settings.raw
50
+ puts JSON.pretty_generate lists
51
+ else
52
+ lists.each do |list|
53
+ puts "#{list[ "name" ]}"
54
+ end
55
+ end
56
+ end
57
+
58
+ desc "get-cards", "Get cards"
59
+ option "board-id", :desc => "Id of Trello board", :required => true
60
+ def get_cards
61
+ process_global_options options
62
+ require_trello_credentials
63
+
64
+ trello = Trello.new(board_id: options["board-id"], developer_public_key: @@settings.developer_public_key, member_token: @@settings.member_token)
65
+
66
+ cards = trello.cards
67
+
68
+ if @@settings.raw
69
+ puts JSON.pretty_generate cards
70
+ else
71
+ burndown = BurndownData.new @@settings
72
+ burndown.board_id = options["board-id"]
73
+
74
+ todo_list_id = burndown.fetch_todo_list_id
75
+ doing_list_id = burndown.fetch_doing_list_id
76
+ done_list_id = burndown.fetch_done_list_id
77
+
78
+ cards_todo = Array.new
79
+ cards_doing = Array.new
80
+ cards_done = Array.new
81
+
82
+ above_waterline = true
83
+
84
+ cards.each do |card|
85
+ name = card["name"]
86
+ list = card["idList"]
87
+ puts "CARD #{name} (#{list})"
88
+
89
+ if name == "Waterline"
90
+ above_waterline = false
91
+ next
92
+ end
93
+
94
+ if Card.name_to_points(name).nil?
95
+ next
96
+ end
97
+
98
+ if list == todo_list_id && above_waterline
99
+ cards_todo.push card
100
+ elsif list == doing_list_id
101
+ cards_doing.push card
102
+ elsif list == done_list_id
103
+ cards_done.push card
104
+ end
105
+ end
106
+
107
+ story_points_todo = 0
108
+ story_points_doing = 0
109
+ story_points_done = 0
110
+
111
+ puts
112
+
113
+ puts "Todo"
114
+ cards_todo.each do |card|
115
+ puts " #{card["name"]}"
116
+ story_points_todo += Card.name_to_points(card["name"])
117
+ end
118
+
119
+ puts "Doing"
120
+ cards_doing.each do |card|
121
+ puts " #{card["name"]}"
122
+ story_points_doing += Card.name_to_points(card["name"])
123
+ end
124
+
125
+ puts "Done"
126
+ cards_done.each do |card|
127
+ puts " #{card["name"]}"
128
+ story_points_done += Card.name_to_points(card["name"])
129
+ end
130
+
131
+ puts
132
+
133
+ story_points_total = story_points_todo + story_points_doing + story_points_done
134
+
135
+ puts "Done: #{story_points_done}/#{story_points_total} (#{story_points_doing} in progress)"
136
+ end
137
+ end
138
+
139
+ desc "get-checklists", "Get checklists"
140
+ option "board-id", :desc => "Id of Trello board", :required => true
141
+ def get_checklists
142
+ process_global_options options
143
+ require_trello_credentials
144
+
145
+ trello = Trello.new(board_id: options["board-id"], developer_public_key: @@settings.developer_public_key, member_token: @@settings.member_token)
146
+
147
+ data = trello.checklists
148
+
149
+ puts JSON.pretty_generate data
150
+ end
151
+
152
+ desc "fetch-burndown-data", "Fetch data for burndown chart"
153
+ option "board-id", :desc => "Id of Trello board", :required => true
154
+ def fetch_burndown_data
155
+ process_global_options options
156
+ require_trello_credentials
157
+
158
+ burndown = BurndownData.new @@settings
159
+ burndown.board_id = options["board-id"]
160
+ burndown.fetch
161
+
162
+ puts "Story points:"
163
+ puts " Open: #{burndown.story_points.open}"
164
+ puts " Done: #{burndown.story_points.done}"
165
+ puts " Total: #{burndown.story_points.total}"
166
+ puts "Tasks:"
167
+ puts " Open: #{burndown.tasks.open}"
168
+ puts " Done: #{burndown.tasks.done}"
169
+ puts " Total: #{burndown.tasks.total}"
170
+ puts
171
+ puts "Extra story points:"
172
+ puts " Open: #{burndown.extra_story_points.open}"
173
+ puts " Done: #{burndown.extra_story_points.done}"
174
+ puts " Total: #{burndown.extra_story_points.total}"
175
+ puts "Extra tasks:"
176
+ puts " Open: #{burndown.extra_tasks.open}"
177
+ puts " Done: #{burndown.extra_tasks.done}"
178
+ puts " Total: #{burndown.extra_tasks.total}"
179
+ end
180
+
181
+ desc "burndown-init", "Initialize burndown chart"
182
+ option :output, :aliases => :o, :desc => "Output directory", :required => true
183
+ option "board-id", :desc => "Id of Trello board", :required => true
184
+ def burndown_init command=nil
185
+ process_global_options options
186
+ require_trello_credentials
187
+
188
+ chart = BurndownChart.new @@settings
189
+ puts "Preparing directory..."
190
+ chart.setup(options[:output],options["board-id"])
191
+ end
192
+
193
+ desc "burndown", "Update burndown chart"
194
+ option :output, :aliases => :o, :desc => "Output directory", :required => false
195
+ option :new_sprint, :aliases => :n, :desc => "Create new sprint"
196
+ def burndown
197
+ process_global_options options
198
+ require_trello_credentials
199
+
200
+ chart = BurndownChart.new @@settings
201
+ begin
202
+ if options[:new_sprint]
203
+ chart.create_next_sprint(options[:output] || Dir.pwd)
204
+ end
205
+ chart.update(options[:output] || Dir.pwd)
206
+ rescue TrolloloError => e
207
+ STDERR.puts e
208
+ exit 1
209
+ end
210
+ end
211
+
212
+ desc "plot", "Plot burndown chart"
213
+ def plot(sprint_number)
214
+ process_global_options options
215
+
216
+ plot_helper = File.expand_path("../../scripts/create_burndown.py", __FILE__ )
217
+ system "python #{plot_helper} #{sprint_number}"
218
+ end
219
+
220
+ private
221
+
222
+ def process_global_options options
223
+ @@settings.verbose = options[:verbose]
224
+ @@settings.raw = options[:raw]
225
+ end
226
+
227
+ def require_trello_credentials
228
+ write_back = false
229
+
230
+ if !@@settings.developer_public_key
231
+ puts "Put in Trello developer public key:"
232
+ @@settings.developer_public_key = STDIN.gets.chomp
233
+ write_back = true
234
+ end
235
+
236
+ if !@@settings.member_token
237
+ puts "Put in Trello member token:"
238
+ @@settings.member_token = STDIN.gets.chomp
239
+ write_back = true
240
+ end
241
+
242
+ if write_back
243
+ @@settings.save_config
244
+ end
245
+
246
+ if !@@settings.developer_public_key || !@@settings.member_token
247
+ STDERR.puts "Require trello credentials in config file"
248
+ exit 1
249
+ end
250
+ end
251
+ end
@@ -0,0 +1,54 @@
1
+ # Copyright (c) 2013-2014 SUSE LLC
2
+ #
3
+ # This program is free software; you can redistribute it and/or
4
+ # modify it under the terms of version 3 of the GNU General Public License as
5
+ # published by the Free Software Foundation.
6
+ #
7
+ # This program is distributed in the hope that it will be useful,
8
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
+ # GNU General Public License for more details.
11
+ #
12
+ # You should have received a copy of the GNU General Public License
13
+ # along with this program; if not, contact SUSE LLC.
14
+ #
15
+ # To contact SUSE about this file by physical or electronic mail,
16
+ # you may find current contact information at www.suse.com
17
+
18
+ class Settings
19
+
20
+ attr_accessor :verbose, :raw
21
+ attr_accessor :developer_public_key, :member_token
22
+
23
+ def initialize config_file_path
24
+ @config_file_path = config_file_path
25
+ if File.exists? config_file_path
26
+ @config = YAML.load_file(config_file_path)
27
+
28
+ if @config
29
+ @developer_public_key = @config["developer_public_key"]
30
+ @member_token = @config["member_token"]
31
+ else
32
+ raise "Couldn't read config data from '#{config_file_path}'"
33
+ end
34
+ end
35
+
36
+ @verbose = false
37
+ @raw = false
38
+ end
39
+
40
+ def save_config
41
+ @config = {}
42
+ @config["developer_public_key"] = @developer_public_key
43
+ @config["member_token"] = @member_token
44
+
45
+ File.open(@config_file_path,"w") do |f|
46
+ f.write(@config.to_yaml)
47
+ end
48
+ end
49
+
50
+ def version
51
+ Trollolo::VERSION
52
+ end
53
+
54
+ end
@@ -0,0 +1,66 @@
1
+ # Copyright (c) 2013-2014 SUSE LLC
2
+ #
3
+ # This program is free software; you can redistribute it and/or
4
+ # modify it under the terms of version 3 of the GNU General Public License as
5
+ # published by the Free Software Foundation.
6
+ #
7
+ # This program is distributed in the hope that it will be useful,
8
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
+ # GNU General Public License for more details.
11
+ #
12
+ # You should have received a copy of the GNU General Public License
13
+ # along with this program; if not, contact SUSE LLC.
14
+ #
15
+ # To contact SUSE about this file by physical or electronic mail,
16
+ # you may find current contact information at www.suse.com
17
+
18
+ class Trello
19
+ class ApiError < StandardError; end
20
+
21
+ attr_accessor :board_id
22
+
23
+ attr_reader :developer_public_key, :member_token
24
+
25
+ def initialize settings
26
+ @developer_public_key = settings.fetch(:developer_public_key)
27
+ @member_token = settings.fetch(:member_token)
28
+ @board_id = settings.fetch(:board_id)
29
+ end
30
+
31
+ def lists
32
+ get "lists"
33
+ end
34
+
35
+ def cards
36
+ get "cards"
37
+ end
38
+
39
+ def checklists
40
+ get "checklists"
41
+ end
42
+
43
+ private
44
+
45
+ def resource_url resource
46
+ "/1/boards/#{board_id}/#{resource}?key=#{developer_public_key}&token=#{member_token}"
47
+ end
48
+
49
+ # FIXME: we should handle time-outs gracefully.
50
+
51
+ def get resource
52
+ resp = http_client.get resource_url(resource)
53
+ unless resp.code == "200"
54
+ raise ApiError.new("Error occured while connecting to the trello API.")
55
+ end
56
+ JSON.parse(resp.body)
57
+ rescue JSON::ParserError => e
58
+ raise ApiError.new(e)
59
+ end
60
+
61
+ def http_client
62
+ http = Net::HTTP.new "trello.com", 443
63
+ http.use_ssl = true
64
+ http
65
+ end
66
+ end
@@ -0,0 +1,34 @@
1
+ # Copyright (c) 2013-2014 SUSE LLC
2
+ #
3
+ # This program is free software; you can redistribute it and/or
4
+ # modify it under the terms of version 3 of the GNU General Public License as
5
+ # published by the Free Software Foundation.
6
+ #
7
+ # This program is distributed in the hope that it will be useful,
8
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
+ # GNU General Public License for more details.
11
+ #
12
+ # You should have received a copy of the GNU General Public License
13
+ # along with this program; if not, contact SUSE LLC.
14
+ #
15
+ # To contact SUSE about this file by physical or electronic mail,
16
+ # you may find current contact information at www.suse.com
17
+
18
+ require "thor"
19
+ require "net/http"
20
+ require "net/https"
21
+ require "json"
22
+ require "yaml"
23
+ require "erb"
24
+
25
+ require_relative 'version'
26
+ require_relative 'cli'
27
+ require_relative 'settings'
28
+ require_relative 'trello'
29
+ require_relative 'card'
30
+ require_relative 'burndown_chart'
31
+ require_relative 'burndown_data'
32
+
33
+ class TrolloloError < StandardError
34
+ end