hu 1.3.16 → 1.3.17
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop_todo.yml +13 -7
- data/hu.gemspec +3 -1
- data/lib/hu/common.rb +8 -0
- data/lib/hu/deploy.rb +40 -4
- data/lib/hu/telemetry.rb +71 -0
- data/lib/hu/version.rb +1 -1
- metadata +35 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 940552e283a3cc03909ec0c01427ba5cc69df5ff
|
4
|
+
data.tar.gz: 1d0c4fde9af5ac93aa8dbd2f3e5597a6afa617cc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 145d01c855f29a2404f2dfa902e05cc7198d054b2592fe21e306c604fc0e86ca9f91f267b48227ca1e44af5a06a19f7344368afbca4a188e5cdfadb6bfc80a9e
|
7
|
+
data.tar.gz: 8ccd30130baf37129041ad3c8d253b42a788519cd431f8c9d3dbac21626322e7ce696e026409c2ca440f66b35ca4a372cb234012a424aaa334d02d5bb6063bfc
|
data/.rubocop_todo.yml
CHANGED
@@ -1,26 +1,31 @@
|
|
1
|
-
# Offense count:
|
1
|
+
# Offense count: 1
|
2
|
+
Lint/HandleExceptions:
|
3
|
+
Exclude:
|
4
|
+
- 'lib/hu/telemetry.rb'
|
5
|
+
|
6
|
+
# Offense count: 14
|
2
7
|
Metrics/AbcSize:
|
3
|
-
Max:
|
8
|
+
Max: 298
|
4
9
|
|
5
10
|
# Offense count: 2
|
6
11
|
# Configuration parameters: CountComments.
|
7
12
|
Metrics/ClassLength:
|
8
|
-
Max:
|
13
|
+
Max: 694
|
9
14
|
|
10
15
|
# Offense count: 6
|
11
16
|
Metrics/CyclomaticComplexity:
|
12
17
|
Max: 45
|
13
18
|
|
14
|
-
# Offense count:
|
19
|
+
# Offense count: 86
|
15
20
|
# Configuration parameters: AllowHeredoc, AllowURI, URISchemes.
|
16
21
|
# URISchemes: http, https
|
17
22
|
Metrics/LineLength:
|
18
23
|
Max: 176
|
19
24
|
|
20
|
-
# Offense count:
|
25
|
+
# Offense count: 16
|
21
26
|
# Configuration parameters: CountComments.
|
22
27
|
Metrics/MethodLength:
|
23
|
-
Max:
|
28
|
+
Max: 254
|
24
29
|
|
25
30
|
# Offense count: 4
|
26
31
|
Metrics/PerceivedComplexity:
|
@@ -31,7 +36,7 @@ Style/ClassVars:
|
|
31
36
|
Exclude:
|
32
37
|
- 'lib/hu/deploy.rb'
|
33
38
|
|
34
|
-
# Offense count:
|
39
|
+
# Offense count: 6
|
35
40
|
Style/Documentation:
|
36
41
|
Exclude:
|
37
42
|
- 'spec/**/*'
|
@@ -40,6 +45,7 @@ Style/Documentation:
|
|
40
45
|
- 'lib/hu/collab.rb'
|
41
46
|
- 'lib/hu/common.rb'
|
42
47
|
- 'lib/hu/deploy.rb'
|
48
|
+
- 'lib/hu/telemetry.rb'
|
43
49
|
|
44
50
|
# Offense count: 3
|
45
51
|
# Configuration parameters: AllowedVariables.
|
data/hu.gemspec
CHANGED
@@ -31,7 +31,7 @@ Gem::Specification.new do |spec|
|
|
31
31
|
spec.add_dependency 'hashdiff', '~> 0.3.0'
|
32
32
|
spec.add_dependency 'version_sorter', '~> 2.0.0'
|
33
33
|
spec.add_dependency 'versionomy', '~> 0.5.0'
|
34
|
-
spec.add_dependency 'tty-prompt'
|
34
|
+
spec.add_dependency 'tty-prompt', '~> 0.6.0'
|
35
35
|
spec.add_dependency 'tty-spinner'
|
36
36
|
spec.add_dependency 'tty-table'
|
37
37
|
spec.add_dependency 'rainbow'
|
@@ -41,4 +41,6 @@ Gem::Specification.new do |spec|
|
|
41
41
|
spec.add_dependency 'rugged'
|
42
42
|
spec.add_dependency 'paint'
|
43
43
|
spec.add_dependency 'lolcat'
|
44
|
+
spec.add_dependency 'analytics-ruby'
|
45
|
+
spec.add_dependency 'config'
|
44
46
|
end
|
data/lib/hu/common.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
require 'blackbox/gem'
|
3
|
+
require 'config'
|
3
4
|
|
4
5
|
module Hu
|
5
6
|
API_TOKEN = ENV['HEROKU_API_KEY'] || ENV['HEROKU_API_TOKEN'] || Netrc.read['api.heroku.com']&.password
|
7
|
+
CONFIG_FILE = File.join(ENV['HOME'], '.hu.yaml')
|
6
8
|
end
|
7
9
|
|
8
10
|
class String
|
@@ -12,9 +14,13 @@ class String
|
|
12
14
|
end
|
13
15
|
end
|
14
16
|
|
17
|
+
Config.load_and_set_settings Hu::CONFIG_FILE
|
18
|
+
require 'hu/telemetry'
|
19
|
+
|
15
20
|
unless ENV['SKIP_VERSION_CHECK']
|
16
21
|
version_info = BB::Gem.version_info(check_interval: 900)
|
17
22
|
unless version_info[:installed_is_latest] == true
|
23
|
+
Hu::Tm.t(:gem_outdated, installed_version: version_info[:gem_installed_version], available_version: version_info[:gem_latest_version])
|
18
24
|
puts
|
19
25
|
puts "\e[33;1mWoops! \e[0mA newer version of #{version_info[:gem_name]} is available."
|
20
26
|
puts " Please type '\e[1mgem install #{version_info[:gem_name]}\e[0m' to upgrade (v#{version_info[:gem_installed_version]} -> v#{version_info[:gem_latest_version]})."
|
@@ -23,3 +29,5 @@ unless ENV['SKIP_VERSION_CHECK']
|
|
23
29
|
exit 1
|
24
30
|
end
|
25
31
|
end
|
32
|
+
|
33
|
+
Hu::Tm.t(:launch)
|
data/lib/hu/deploy.rb
CHANGED
@@ -39,10 +39,11 @@ module Hu
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def deploy(_cmd, _opts, _argv)
|
42
|
+
Hu::Tm.t(:invoke, cmd: 'deploy')
|
42
43
|
trap('INT') { shutdown; safe_abort; exit 1 }
|
43
44
|
at_exit do
|
45
|
+
shutdown
|
44
46
|
if $ERROR_INFO.class == SystemExit && 130 == $ERROR_INFO.status
|
45
|
-
shutdown
|
46
47
|
puts
|
47
48
|
safe_abort
|
48
49
|
end
|
@@ -57,6 +58,7 @@ module Hu
|
|
57
58
|
puts
|
58
59
|
safe_abort
|
59
60
|
print TTY::Cursor.prev_line
|
61
|
+
Hu::Tm.t(:error_not_in_working_copy, cmd: 'deploy')
|
60
62
|
exit 1
|
61
63
|
end
|
62
64
|
|
@@ -68,6 +70,7 @@ module Hu
|
|
68
70
|
puts
|
69
71
|
puts ' Sorry, we need an origin here. We really do.'
|
70
72
|
puts
|
73
|
+
Hu::Tm.t(:error_no_git_origin, cmd: 'deploy')
|
71
74
|
exit 1
|
72
75
|
end
|
73
76
|
|
@@ -77,6 +80,7 @@ module Hu
|
|
77
80
|
puts
|
78
81
|
puts " Please run 'git flow init -d'"
|
79
82
|
puts
|
83
|
+
Hu::Tm.t(:error_no_git_flow, cmd: 'deploy')
|
80
84
|
exit 1
|
81
85
|
end
|
82
86
|
|
@@ -89,6 +93,7 @@ module Hu
|
|
89
93
|
puts
|
90
94
|
puts " git config --add gitflow.prefix.versiontag ''".bright
|
91
95
|
puts
|
96
|
+
Hu::Tm.t(:error_git_flow_prefix_enabled, cmd: 'deploy')
|
92
97
|
exit 1
|
93
98
|
end
|
94
99
|
|
@@ -105,6 +110,7 @@ module Hu
|
|
105
110
|
puts
|
106
111
|
puts " Please run 'git remote rm heroku'. Then run 'hu deploy' again to select a new remote."
|
107
112
|
puts
|
113
|
+
Hu::Tm.t(:error_no_heroku_app_for_remote, cmd: 'deploy')
|
108
114
|
exit 1
|
109
115
|
end
|
110
116
|
|
@@ -120,6 +126,7 @@ module Hu
|
|
120
126
|
|
121
127
|
puts " Please run 'git remote rm heroku'. Then run 'hu deploy' again to select a new remote."
|
122
128
|
puts
|
129
|
+
Hu::Tm.t(:error_remote_not_staging, cmd: 'deploy')
|
123
130
|
sleep 2
|
124
131
|
exit 1
|
125
132
|
end
|
@@ -199,6 +206,7 @@ module Hu
|
|
199
206
|
puts ' Nothing else has happened so far. Push this branch to'
|
200
207
|
puts ' ' + stag_app_name.to_s.bright + ' to begin the deploy procedure.'
|
201
208
|
puts
|
209
|
+
Hu::Tm.t(:phase1, cmd: 'deploy')
|
202
210
|
end
|
203
211
|
|
204
212
|
if release_branch_exists && git_revisions[:release] == git_revisions[stag_app_name]
|
@@ -207,6 +215,7 @@ module Hu
|
|
207
215
|
puts ' If everything looks good, you may proceed and finish the release.'
|
208
216
|
puts ' If there are problems: Quit, delete the release branch and start fixing.'
|
209
217
|
puts
|
218
|
+
Hu::Tm.t(:phase2, cmd: 'deploy')
|
210
219
|
elsif git_revisions[prod_app_name] != git_revisions[stag_app_name] && !release_branch_exists && git_revisions[:release] != git_revisions[stag_app_name]
|
211
220
|
puts 'Phase 3/3: HEADS UP. This is the last chance to detect problems.'
|
212
221
|
puts ' The final version of ' + "release/#{release_tag}".bright + ' is now staged.'
|
@@ -217,6 +226,7 @@ module Hu
|
|
217
226
|
puts ' This is the exact version that will be promoted to production.'
|
218
227
|
puts " From here you are on your own. Good luck #{`whoami`.chomp}!"
|
219
228
|
puts
|
229
|
+
Hu::Tm.t(:phase3, cmd: 'deploy')
|
220
230
|
end
|
221
231
|
|
222
232
|
choice = prompt.select('Choose your destiny') do |menu|
|
@@ -251,9 +261,12 @@ module Hu
|
|
251
261
|
|
252
262
|
case choice
|
253
263
|
when :DEPLOY
|
264
|
+
Hu::Tm.t(:promote_begin, cmd: 'deploy')
|
254
265
|
promote_to_production
|
266
|
+
Hu::Tm.t(:promote_end, cmd: 'deploy')
|
255
267
|
anykey
|
256
268
|
when :finish_release
|
269
|
+
Hu::Tm.t(:finish_begin, cmd: 'deploy')
|
257
270
|
old_editor = ENV['EDITOR']
|
258
271
|
old_git_editor = ENV['GIT_EDITOR']
|
259
272
|
tf = Tempfile.new('hu-tag')
|
@@ -270,36 +283,45 @@ module Hu
|
|
270
283
|
puts '*** ERROR! Could not finish release *** '.color(:red)
|
271
284
|
puts
|
272
285
|
puts 'This usually means a merge conflict or'
|
273
|
-
puts 'something
|
286
|
+
puts 'something equally annoying has occured.'
|
274
287
|
puts
|
275
288
|
puts 'Please bring the universe into a state'
|
276
|
-
puts 'where the above
|
289
|
+
puts 'where the above sequence of commands can'
|
290
|
+
puts 'succeed. Then try again.'
|
277
291
|
puts
|
292
|
+
Hu::Tm.t(:finish_fail, cmd: 'deploy')
|
278
293
|
exit 1
|
279
294
|
end
|
280
295
|
ENV['EDITOR'] = old_editor
|
281
296
|
ENV['GIT_EDITOR'] = old_git_editor
|
297
|
+
Hu::Tm.t(:finish_end, cmd: 'deploy')
|
282
298
|
anykey
|
283
299
|
when :push_to_staging
|
300
|
+
Hu::Tm.t(:stage_begin, cmd: 'deploy')
|
284
301
|
run_each <<-EOS.strip_heredoc
|
285
302
|
:stream
|
286
303
|
git push #{push_url} release/#{release_tag}:master -f
|
287
304
|
EOS
|
305
|
+
Hu::Tm.t(:stage_end, cmd: 'deploy')
|
288
306
|
anykey
|
289
307
|
when :abort_ask
|
308
|
+
Hu::Tm.t(:user_quit, cmd: 'deploy')
|
290
309
|
puts if delete_branch("release/#{release_tag}")
|
291
310
|
exit 0
|
292
311
|
when :bump_tiny
|
293
312
|
if delete_branch("release/#{release_tag}")
|
294
313
|
release_tag, branch_already_exists = prompt_for_release_tag(tiny_bump, tiny_bump)
|
314
|
+
Hu::Tm.t(:switch_release_type, bump: 'patch', cmd: 'deploy')
|
295
315
|
end
|
296
316
|
when :bump_minor
|
297
317
|
if delete_branch("release/#{release_tag}")
|
298
318
|
release_tag, branch_already_exists = prompt_for_release_tag(minor_bump, minor_bump)
|
319
|
+
Hu::Tm.t(:switch_release_type, bump: 'minor', cmd: 'deploy')
|
299
320
|
end
|
300
321
|
when :bump_major
|
301
322
|
if delete_branch("release/#{release_tag}")
|
302
323
|
release_tag, branch_already_exists = prompt_for_release_tag(major_bump, major_bump)
|
324
|
+
Hu::Tm.t(:switch_release_type, bump: 'major', cmd: 'deploy')
|
303
325
|
end
|
304
326
|
end
|
305
327
|
end
|
@@ -396,6 +418,7 @@ module Hu
|
|
396
418
|
puts
|
397
419
|
|
398
420
|
puts table.render(:unicode, padding: [0, 1, 0, 1], multiline: true)
|
421
|
+
Hu::Tm.t(:status_screen, cmd: 'deploy')
|
399
422
|
revs
|
400
423
|
end
|
401
424
|
|
@@ -514,6 +537,8 @@ module Hu
|
|
514
537
|
next unless status.exitstatus != 0
|
515
538
|
shutdown if opts[:failfast]
|
516
539
|
puts "Error, exit #{status.exitstatus}: #{line} (L#{i})".color(:red).bright
|
540
|
+
|
541
|
+
Hu::Tm.t(:runeach_error, exitstatus: status.exitstatus, cmd: 'deploy')
|
517
542
|
exit status.exitstatus if opts[:failfast]
|
518
543
|
return status.exitstatus
|
519
544
|
end
|
@@ -527,7 +552,13 @@ module Hu
|
|
527
552
|
exit status.exitstatus
|
528
553
|
end
|
529
554
|
|
530
|
-
versions = output.lines.map(&:chomp).reject
|
555
|
+
versions = output.lines.map(&:chomp).reject do |e|
|
556
|
+
begin
|
557
|
+
Versionomy.parse(e)
|
558
|
+
rescue
|
559
|
+
true
|
560
|
+
end; false
|
561
|
+
end
|
531
562
|
versions = versions.map { |e| e[0].casecmp('v').zero? ? e.downcase : "v#{e.downcase}" }
|
532
563
|
versions = VersionSorter.sort(versions)
|
533
564
|
latest = versions[-1] || 'v0.0.0'
|
@@ -549,6 +580,7 @@ module Hu
|
|
549
580
|
git checkout develop
|
550
581
|
git branch -D #{branch_name}
|
551
582
|
EOS
|
583
|
+
Hu::Tm.t(:delete_release_branch, cmd: 'deploy')
|
552
584
|
puts "Branch #{branch_name} deleted.".color(:red)
|
553
585
|
true
|
554
586
|
end
|
@@ -566,6 +598,7 @@ module Hu
|
|
566
598
|
# Starting release #{release_tag.color(:green)}
|
567
599
|
git flow release start #{release_tag} >/dev/null
|
568
600
|
EOS
|
601
|
+
Hu::Tm.t(:start_release, cmd: 'deploy')
|
569
602
|
end
|
570
603
|
|
571
604
|
def update_working_copy
|
@@ -576,6 +609,7 @@ module Hu
|
|
576
609
|
git checkout develop && git pull
|
577
610
|
git checkout master && git pull --rebase origin master
|
578
611
|
EOS
|
612
|
+
Hu::Tm.t(:update_working_copy, cmd: 'deploy')
|
579
613
|
end
|
580
614
|
|
581
615
|
def heroku_git_remote
|
@@ -736,6 +770,7 @@ module Hu
|
|
736
770
|
# Abort failed merge
|
737
771
|
git merge --abort
|
738
772
|
EOS
|
773
|
+
Hu::Tm.t(:abort_merge, cmd: 'deploy')
|
739
774
|
end
|
740
775
|
|
741
776
|
def create_changelog(env)
|
@@ -748,6 +783,7 @@ module Hu
|
|
748
783
|
end
|
749
784
|
|
750
785
|
def shutdown
|
786
|
+
Hu::Tm.flush!
|
751
787
|
@@shutting_down = true
|
752
788
|
unbusy
|
753
789
|
end
|
data/lib/hu/telemetry.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'segment'
|
3
|
+
require 'tty-prompt'
|
4
|
+
require 'securerandom'
|
5
|
+
|
6
|
+
module Hu
|
7
|
+
class Tm
|
8
|
+
API_TOKEN = ENV['HEROKU_API_KEY'] || ENV['HEROKU_API_TOKEN'] || Netrc.read['api.heroku.com']&.password
|
9
|
+
@segment = nil
|
10
|
+
@context = {}
|
11
|
+
|
12
|
+
class << self
|
13
|
+
def t(event, props = {})
|
14
|
+
return if @segment.nil?
|
15
|
+
@segment.track(anonymous_id: Settings.userid,
|
16
|
+
event: event.to_s,
|
17
|
+
properties: props,
|
18
|
+
context: @context)
|
19
|
+
end
|
20
|
+
|
21
|
+
def flush!
|
22
|
+
return if @segment.nil?
|
23
|
+
@segment.flush
|
24
|
+
end
|
25
|
+
|
26
|
+
def start!
|
27
|
+
if Settings.send_anonymous_usage_statistics.nil?
|
28
|
+
puts <<-EOF.strip_heredoc
|
29
|
+
|
30
|
+
Hu would like to collect anonymous usage
|
31
|
+
statistics for the purpose of self-improvement.
|
32
|
+
|
33
|
+
No personal data or identifying information
|
34
|
+
about your projects will be collected.
|
35
|
+
|
36
|
+
EOF
|
37
|
+
|
38
|
+
prompt = TTY::Prompt.new
|
39
|
+
choice = prompt.select('Enable anonymous usage statistics?') do |menu|
|
40
|
+
menu.enum '.'
|
41
|
+
menu.choice 'Yes, I will help Hu!', true
|
42
|
+
menu.choice 'Nope', false
|
43
|
+
end
|
44
|
+
|
45
|
+
cfg = {
|
46
|
+
userid: SecureRandom.uuid
|
47
|
+
}
|
48
|
+
begin
|
49
|
+
cfg = YAML.parse(File.read(Hu::CONFIG_FILE))
|
50
|
+
rescue
|
51
|
+
end
|
52
|
+
cfg['send_anonymous_usage_statistics'] = choice
|
53
|
+
File.write(Hu::CONFIG_FILE, YAML.dump(cfg))
|
54
|
+
|
55
|
+
puts "\nThanks!\n"
|
56
|
+
puts "Your decision was saved to #{Hu::CONFIG_FILE}\n"
|
57
|
+
sleep 3
|
58
|
+
end
|
59
|
+
|
60
|
+
if Settings.send_anonymous_usage_statistics == true
|
61
|
+
@segment = Segment::Analytics.new(write_key: 'T32sCm68MMAsyoa9r5uPtHz0YwJ3MjXI')
|
62
|
+
@context = { version: Hu::VERSION }
|
63
|
+
@segment.identify(anonymous_id: Settings.userid || SecureRandom.uuid,
|
64
|
+
context: @context)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
Hu::Tm.start!
|
data/lib/hu/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hu
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.3.
|
4
|
+
version: 1.3.17
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- moe
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-05-
|
11
|
+
date: 2016-05-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -154,16 +154,16 @@ dependencies:
|
|
154
154
|
name: tty-prompt
|
155
155
|
requirement: !ruby/object:Gem::Requirement
|
156
156
|
requirements:
|
157
|
-
- - "
|
157
|
+
- - "~>"
|
158
158
|
- !ruby/object:Gem::Version
|
159
|
-
version:
|
159
|
+
version: 0.6.0
|
160
160
|
type: :runtime
|
161
161
|
prerelease: false
|
162
162
|
version_requirements: !ruby/object:Gem::Requirement
|
163
163
|
requirements:
|
164
|
-
- - "
|
164
|
+
- - "~>"
|
165
165
|
- !ruby/object:Gem::Version
|
166
|
-
version:
|
166
|
+
version: 0.6.0
|
167
167
|
- !ruby/object:Gem::Dependency
|
168
168
|
name: tty-spinner
|
169
169
|
requirement: !ruby/object:Gem::Requirement
|
@@ -290,6 +290,34 @@ dependencies:
|
|
290
290
|
- - ">="
|
291
291
|
- !ruby/object:Gem::Version
|
292
292
|
version: '0'
|
293
|
+
- !ruby/object:Gem::Dependency
|
294
|
+
name: analytics-ruby
|
295
|
+
requirement: !ruby/object:Gem::Requirement
|
296
|
+
requirements:
|
297
|
+
- - ">="
|
298
|
+
- !ruby/object:Gem::Version
|
299
|
+
version: '0'
|
300
|
+
type: :runtime
|
301
|
+
prerelease: false
|
302
|
+
version_requirements: !ruby/object:Gem::Requirement
|
303
|
+
requirements:
|
304
|
+
- - ">="
|
305
|
+
- !ruby/object:Gem::Version
|
306
|
+
version: '0'
|
307
|
+
- !ruby/object:Gem::Dependency
|
308
|
+
name: config
|
309
|
+
requirement: !ruby/object:Gem::Requirement
|
310
|
+
requirements:
|
311
|
+
- - ">="
|
312
|
+
- !ruby/object:Gem::Version
|
313
|
+
version: '0'
|
314
|
+
type: :runtime
|
315
|
+
prerelease: false
|
316
|
+
version_requirements: !ruby/object:Gem::Requirement
|
317
|
+
requirements:
|
318
|
+
- - ">="
|
319
|
+
- !ruby/object:Gem::Version
|
320
|
+
version: '0'
|
293
321
|
description: Heroku Utility.
|
294
322
|
email:
|
295
323
|
- moe@busyloop.net
|
@@ -311,6 +339,7 @@ files:
|
|
311
339
|
- lib/hu/collab.rb
|
312
340
|
- lib/hu/common.rb
|
313
341
|
- lib/hu/deploy.rb
|
342
|
+
- lib/hu/telemetry.rb
|
314
343
|
- lib/hu/version.rb
|
315
344
|
homepage: https://github.com/busyloop/hu
|
316
345
|
licenses:
|