blend 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,493 @@
1
+ module Blend
2
+ module CLI
3
+ class Juice < Thor
4
+ desc "login", "Login to juice"
5
+ def login
6
+ puts "Logged in." if client.login
7
+ end
8
+
9
+ desc "logout", "Clear juice credentials"
10
+ def logout
11
+ puts "Juice credentials cleared." if client.logout
12
+ end
13
+
14
+ desc "open PROJECT", "Open up juice"
15
+ def open( name )
16
+ project_id = project_id_from_name name
17
+ if( project_id.nil? )
18
+ puts "#{name} not found"
19
+ return
20
+ end
21
+
22
+ system "open http://happyfunjuice.com/projects/#{project_id}"
23
+ end
24
+
25
+ desc "settings PROJECT", "Open up juice settings"
26
+ def settings(name)
27
+ project_id = project_id_from_name name
28
+ if( project_id.nil? )
29
+ puts "#{name} not found"
30
+ return
31
+ end
32
+
33
+ system "open http://happyfunjuice.com/projects/#{project_id}/overview"
34
+ end
35
+
36
+ desc "create PROJECT", "Create a juice project"
37
+ def create( name )
38
+ puts "TIP: you can also run check #{name} to set up everything"
39
+ client.create_project( name )
40
+ end
41
+
42
+ desc "projects", "List juice projects"
43
+ def projects
44
+ puts
45
+ printf "%-25s %-10s %-10s %-25s\n".blue, '', 'Commits', 'Deploys', '', ''
46
+ printf "%-25s %-10s %-10s %-25s\n".blue, '', 'this', 'this', '', ''
47
+ printf "%-25s %-10s %-10s %-25s %s\n".underline.blue, 'Name', 'wk', 'wk', 'Hipchat room', 'Teams'
48
+ client.summary.sort{|a,b| b['name'].to_i <=> a['name'].to_i}.each_with_index do |project,i|
49
+ printf "%-25s %-10s %-10s %-25s %s\n".try{|x| i%4==3 ? x.underline : x},
50
+ #project['id'],
51
+ project['name'].projectize,
52
+ (project['has_source_feeds'] ? project['commits_this_week'] : ''),
53
+ (project['has_server_feeds'] ? project['deploys_this_week'] : ''),
54
+ project['blend_config']['hipchat_room'],
55
+ project['blend_config']['teams'].join( ',' )
56
+ end
57
+ puts
58
+ end
59
+
60
+ desc "organizations", "Get a list of your organizations"
61
+ def organizations
62
+ puts
63
+ printf "%-5s %-25s %-25s\n".underline.blue, 'ID', 'Name', 'Domain name'
64
+ client.organizations.each do |o|
65
+ printf "%-5s %-25s %-25s\n", o['id'], o['name'], o['domain_name']
66
+ end
67
+ puts
68
+ end
69
+
70
+
71
+ desc "feeds PROJECT", "Show the configured juice feeds"
72
+ def feeds(name)
73
+ puts
74
+ printf "%-30s %-20s %-30s\n".blue.underline, 'Feed', 'Environment', 'Namespace'
75
+ client.feeds( project_id_from_name( name ) ).sort do
76
+ |a,b| a['feed_name'] <=> b['feed_name']
77
+ end.each do |feed|
78
+ printf "%-30s %-20s %-30s\n",
79
+ feed['feed_name'],
80
+ (feed['environment'] || {})['name'],
81
+ [feed['namespace'],feed['name']].select {|x| x}.join( '/' )
82
+ end
83
+ puts
84
+ end
85
+
86
+ desc "users [PROJECT]", "Get a list of users"
87
+ def users( name=nil )
88
+
89
+ if name.nil?
90
+ _users = client.organization_users( 1 ) # Hard-code hfc org here
91
+ else
92
+ _users = client.project_users( project_id_from_name( name ) )
93
+ end
94
+
95
+ puts
96
+ printf "%-25s %35s %35s %35s %35s\n".blue.underline, 'Name', 'Email', 'Personal email', 'Heroku', 'Github'
97
+ _users.each do |u|
98
+ printf "%-25s %35s %35s %35s %35s\n", u['name'], u['email'], u['personal_email'], u['heroku_handle'], u['github_handle']
99
+ end
100
+ puts
101
+ end
102
+
103
+ desc "add_team PROJECT TEAM", "Add a github team to a project"
104
+ def add_team( name, team )
105
+ client.project_add_team( project_id_from_name( name ), team )
106
+ info( name )
107
+ end
108
+
109
+ desc "add_hipchat PROJECT ROOM", "Add a hipchat room to a project"
110
+ def add_hipchat( name, room )
111
+ client.project_add_hipchat( project_id_from_name( name ), room )
112
+ info( name )
113
+ end
114
+
115
+ desc "lookup_user NAME", "Looks up a user by email address"
116
+ def lookup_user( query )
117
+ pp client.lookup_user( query )
118
+ end
119
+
120
+ desc "search_users QUERY", "Look up a user by name, email, github, heroku, etc."
121
+ def search_users( query )
122
+ puts
123
+ printf "%-25s %35s %35s %35s %35s\n".blue.underline, 'Name', 'Email', 'Personal email', 'Heroku', 'Github'
124
+ client.search_users(query).each do |u|
125
+ printf "%-25s %35s %35s %35s %35s\n", u['name'], u['email'], u['personal_email'], u['heroku_handle'], u['github_handle']
126
+ end
127
+ puts
128
+ end
129
+
130
+ # desc "user_set FIELD VALUE", "Set the value of a particular field for a user"
131
+ # def user_set( field, value )
132
+ # client
133
+ # end
134
+
135
+ desc "heroku_api TOKEN", "Sets the organization heroku token"
136
+ def heroku_api( token )
137
+ client.heroku_api token
138
+ end
139
+
140
+
141
+ desc "hipchat_api TOKEN", "Sets the organization hipchat token"
142
+ def hipchat_api( token )
143
+ client.hipchat_api token
144
+ end
145
+
146
+ desc "all_projects [--resolve]", "Show all project status"
147
+ option :resolve
148
+ def all_projects
149
+ client.projects.each do |p|
150
+ project( p['name'] )
151
+ end
152
+ end
153
+
154
+ desc "project NAME [--resolve]", "Get project status"
155
+ option :resolve
156
+ def project( name )
157
+ status = Blend::Status::Project.new( name, options[:resolve] )
158
+
159
+ status.header "#{name}: Juice Configuration"
160
+ status.check "Project Exists", :project_found
161
+ status.check "Hipchat Room", :hipchat
162
+ status.check "Github Teams", :github_teams
163
+ status.check "Repos Configured", :repos_setup
164
+ status.check "Source Control", :source_control
165
+ status.check "Bug Tracking", :bugtracking
166
+
167
+ status.header "#{name}: Environments"
168
+ status.check "Production", :production
169
+ status.check "Staging", :staging
170
+
171
+ status.header "#{name}: Team Configuration (#{status.github_teams.join(',')})" if status.github_teams.length > 0
172
+
173
+ status.check "Members", :github_members
174
+
175
+ status.check "User Matchup", :juice_users_synced
176
+
177
+ status.github_members.each do |m|
178
+ member = m[:name]
179
+ access = m[:access]
180
+ # puts member
181
+ juice_user = client.user_from_github_user member
182
+ if access == :read
183
+ printf "%-20s %15s".yellow, member, "readonly"
184
+ else
185
+ printf "%-20s %15s".green, member, "fullaccess"
186
+ end
187
+
188
+ if juice_user
189
+ printf " %-20s %s\n", juice_user['name'], juice_user['email']
190
+ else
191
+ puts " Unknown to juice".red
192
+ end
193
+ end
194
+
195
+ status.repo_status.each do |repo|
196
+ status.header "#{repo.name} Configuration"
197
+
198
+ repo.check "Private", :private?
199
+ repo.check "Hipchat Deployhook", :hipchat_hook
200
+ end
201
+
202
+ status.environment_status.each do |env|
203
+ status.header "Server: #{env.server} Configuration"
204
+
205
+ env.check "Dyno Redundancy", :dyno_redundancy
206
+ env.check "Database", :database
207
+ env.check "Backups", :backups
208
+ env.check "Stack", :stack
209
+ env.check "Exception Handling", :exception_handling
210
+ env.check "Deploy Hooks", :deployhooks
211
+ env.check "Log Monitoring", :log_monitoring
212
+ env.check "App Monitoring", :app_monitoring
213
+ env.check "SSL Addon", :ssl
214
+ end
215
+
216
+ status.domains_status.each do |domain|
217
+ status.header "DNS: #{domain.domain} configuration"
218
+
219
+ domain.check "Registered?", :registered?
220
+ domain.check "Expires", :expires
221
+ domain.check "Owner", :owner
222
+ domain.check "SSL Cert", :ssl_exists?
223
+ domain.check "SSL Expires", :ssl_valid_until
224
+ domain.check "SSL Common Name", :ssl_common_name
225
+ end
226
+
227
+ end
228
+ =begin
229
+
230
+
231
+
232
+
233
+ desc "check [PROJECT]", "Check a project config (all the checks)"
234
+ def check( name )
235
+ check_project( name )
236
+ puts
237
+ check_hipchat( name )
238
+ puts
239
+ check_team( name )
240
+ puts
241
+ check_hooks( name )
242
+ puts
243
+ info( name )
244
+ end
245
+
246
+ desc "check_hooks [PROJECT]", "Check to see if the hooks are configured"
247
+ def check_hooks( name )
248
+ puts "Looking for github hooks".bold
249
+ ##
250
+ # Github Hooks
251
+ ##
252
+ project_id = project_id_from_name name
253
+ return if project_id.nil?
254
+
255
+ data = client.project project_id
256
+ config = data['blend_config']
257
+
258
+ teams = config['teams']
259
+
260
+ if teams.count > 0
261
+ teams.each do |team|
262
+ puts "Looking at repos for #{team}".bold
263
+ github_client.list_team_repos( team ).each do |repo|
264
+ printf "%-40s %s\n", repo['full_name'], repo['description']
265
+ found = {}
266
+ github_client.list_hooks( repo['full_name'] ).each do |hook|
267
+ puts "Found #{hook["name"]}"
268
+ found[hook['name']] = true
269
+ end
270
+
271
+ unless found['hipchat']
272
+ puts "Missing hipchat hook"
273
+ if config['hipchat_room']
274
+ puts "Adding Hipchat Hook"
275
+ Blend::CLI::Github.new.add_hipchat( repo['full_name'], config['hipchat_room'])
276
+ else
277
+ puts "Missing hipchat room"
278
+ end
279
+ end
280
+ end
281
+ end
282
+ else
283
+ puts "Teams must be set up correctly in order to monitor hooks.".red
284
+ end
285
+
286
+ apps = client.heroku_apps( project_id )
287
+
288
+
289
+ if( apps['production'] )
290
+ puts "Production".blue
291
+ apps['production'].each do |app|
292
+ Blend::CLI::Heroku.new.check app['name']
293
+ a = heroku_client.addons(app['name'], /deployhooks/)
294
+
295
+ if( a.nil? || a.length == 0 )
296
+ puts "Adding deploy hook".yellow
297
+ system( "echo heroku addons:add deployhooks:hipchat --auth_token=#{client.hipchat_api} --room=\"#{config['hipchat_room']} --app #{app['name']}\"")
298
+ system( "heroku addons:add deployhooks:hipchat --auth_token=#{client.hipchat_api} --room=\"#{config['hipchat_room']}\" --app #{app['name']}")
299
+ Blend::Client::hipchat_client.post_message config['hipchat_room'], "Heroku app: #{app['name']} commit hook now added"
300
+ end
301
+ end
302
+ end
303
+ if( apps['staging'] )
304
+ puts "Staging".blue
305
+ apps['staging'].each do |app|
306
+ Blend::CLI::Heroku.new.check app['name']
307
+ a = heroku_client.addons(app['name'], /deployhooks/)
308
+
309
+ if( a.nil? || a.length == 0 )
310
+ puts "Adding deploy hook".yellow
311
+ system( "echo heroku addons:add deployhooks:hipchat --auth_token=#{client.hipchat_api} --room=\"#{config['hipchat_room']} --app #{app['name']}\"")
312
+ system( "heroku addons:add deployhooks:hipchat --auth_token=#{client.hipchat_api} --room=\"#{config['hipchat_room']} --app #{app['name']}\"")
313
+ Blend::Client::hipchat_client.post_message config['hipchat_room'], "Heroku app: #{app['name']} commit hook now added"
314
+ end
315
+ end
316
+ end
317
+
318
+ end
319
+ =end
320
+
321
+ desc "hipchat_check", "Prints out all the rooms not assigned to rooms"
322
+ def hipchat_check
323
+ begin
324
+ client.hipchat_check.each do |x|
325
+ printf "%-30s %s\n", x[:room], x[:projects].join( "," )
326
+ end
327
+ rescue Exceptions::HipchatAuthenticationFailure
328
+ puts "Unable to connect to Hipchat. Is your key valid?".red
329
+ end
330
+ end
331
+
332
+ desc "github_team_check", "Prints out all the teams not assigned to projects"
333
+ option :fix
334
+ def github_team_check
335
+ client.github_team_check.each do |team,projects|
336
+ next if team == 'Owners'
337
+ next if projects.size > 0
338
+ puts "#{team} has no juice project".red
339
+ # printf "%-30s %s\n", team, projects.collect {|x| x['name'] }.join( "," )
340
+
341
+ if( options[:fix] )
342
+ choices = client.projects.collect { |x| x['name'] }
343
+
344
+ project = choose do |menu|
345
+ menu.header = "Select a github team action"
346
+ menu.prompt = "Please choose a unassigned juice project to associate #{team} with:"
347
+
348
+ menu.choice "Ignore" do
349
+ "ignore"
350
+ end
351
+
352
+ menu.choice "Create a project called #{team}" do
353
+ "create"
354
+ end
355
+
356
+ menu.choices *choices
357
+ end
358
+
359
+ if( project == "ignore" )
360
+ puts "Skip it"
361
+ else
362
+ if( project == "create" )
363
+ puts "TODO: Create a new project called #{team}"
364
+ else
365
+ add_team project, team
366
+ # puts "Attaching to: #{project}"
367
+ end
368
+ end
369
+ end
370
+ end
371
+ end
372
+
373
+ desc "activity PROJECT", "Shows recent project activity in last week or (default) current week [--lastweek] [--thisweek]"
374
+ option :lastweek
375
+ option :thisweek
376
+ def activity( name )
377
+ puts
378
+ project_id = project_id_from_name name
379
+ return if project_id.nil?
380
+
381
+ now = DateTime.now.to_date + 1
382
+ after = now - now.wday
383
+ before = Time.now
384
+
385
+ if( options[:lastweek] )
386
+ after -= 7
387
+ before = after + 7
388
+ end
389
+
390
+ summary = client.activities( project_id, after.to_time, before.to_time )
391
+
392
+ project = client.project( project_id )
393
+
394
+ puts "#{project['name']} activity".bold + " for #{summary[:after].strftime( "%Y-%m-%d %H:%M" )} (#{((Time.now-summary[:after])/3600/24).round(1)} days ago) - #{summary[:before].strftime( "%Y-%m-%d %H:%M" )} (now)"
395
+ puts
396
+ puts "Activity Summary".underline.blue
397
+ summary[:type].keys.sort.each do |x|
398
+ printf "%-6s %s\n", summary[:type][x].count, x
399
+ end
400
+
401
+ puts
402
+ puts "Activity Breakdown".underline.blue
403
+ summary[:actors_activites].keys.sort.each do |x|
404
+ summary[:actors_activites][x].keys.select { |x| x}.sort.each do |type|
405
+ printf "%-6s %-25s %s\n", summary[:actors_activites][x][type].count, type.strip_email, x
406
+ end
407
+ end
408
+
409
+ puts
410
+ puts "New Tickets".underline.blue
411
+ (summary[:type]['bugtracking:openticket'] || []).each do |activity|
412
+ printf "%-15s %-100s\n", activity['actor_identifier'], activity['description'][0..100].gsub( /\n/, " " )
413
+ #puts activity['description'][0..100].gsub( /\n/, " " )
414
+ end
415
+
416
+ puts
417
+ puts "Closed Tickets".underline.blue
418
+ (summary[:type]['bugtracking:closedticket'] || []).each do |activity|
419
+ printf "%-15s %-100s\n", activity['actor_identifier'], activity['description'][0..100].gsub( /\n/, " " )
420
+ #puts activity['description'][0..100].gsub( /\n/, " " )
421
+ end
422
+
423
+ puts
424
+ puts "Active Tickets".underline.blue
425
+ summary[:type].keys.select do |x|
426
+ x =~ /bugtracking/
427
+ end.collect do |x|
428
+ summary[:type][x].collect do |a|
429
+ a['description']
430
+ end
431
+ end.flatten.sort.uniq.each do |x|
432
+ puts x[0..100].gsub( /\n/, " " ) unless x =~ /^\[Changeset\]/
433
+ end
434
+
435
+ puts
436
+ puts "Commits".underline.blue
437
+ (summary[:type]['sourcecontrol:commit'] || []).each do |x|
438
+ printf "%-30s %s\n", x['actor_identifier'].strip_email, x['description'][0..100].gsub( /\n/, " " )
439
+ end
440
+ end
441
+
442
+ desc "report NAME", "Report for an individual project"
443
+ option :lastweek
444
+ def report(name)
445
+ info name
446
+ activity name
447
+ end
448
+
449
+ desc "report_dump", "Write out weekly reports"
450
+ option :lastweek
451
+ def report_dump
452
+ puts "Loading projects"
453
+
454
+ system "mkdir -p /tmp/juice_reports"
455
+ client.projects.each do |project|
456
+ File.open( "/tmp/juice_reports/#{project['name']}.txt", "w" ) do |out|
457
+ puts "Running report for #{project['name']}"
458
+ $stdout = out
459
+ info project['name']
460
+ activities project['name']
461
+ $stdout = STDOUT
462
+ end
463
+ end
464
+ end
465
+
466
+ no_commands do
467
+ def client
468
+ @client ||= Blend::Client.juice_client
469
+ end
470
+
471
+ def hipchat_client
472
+ Blend::Client.hipchat_client
473
+ end
474
+
475
+ def github_client
476
+ Blend::Client.github_client
477
+ end
478
+
479
+ def heroku_client
480
+ Blend::Client.heroku_client
481
+ end
482
+
483
+ def project_id_from_name( name )
484
+ client.project_id_from_name( name )
485
+ end
486
+
487
+ def set( s )
488
+ !s.nil? && s != ""
489
+ end
490
+ end
491
+ end
492
+ end
493
+ end