roku_builder 3.13.0 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +1 -1
- data/CHANGELOG +12 -0
- data/Gemfile.lock +22 -7
- data/Guardfile +3 -3
- data/README.md +22 -398
- data/bin/roku +1 -194
- data/config.json.example +1 -1
- data/intergration/roku_builder/test_core.rb +52 -0
- data/intergration/roku_builder/test_files/core_intergration_test/manifest_template +7 -0
- data/intergration/roku_builder/test_files/core_intergration_test/test.pkg +0 -0
- data/intergration/roku_builder/test_files/inspector_intergration_test/components/rectanglescene.xml +28 -0
- data/intergration/roku_builder/test_files/inspector_intergration_test/images/rde_mm_focus_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/inspector_intergration_test/images/rde_mm_focus_sd.jpg +0 -0
- data/intergration/roku_builder/test_files/inspector_intergration_test/images/rde_splash_fhd.jpg +0 -0
- data/intergration/roku_builder/test_files/inspector_intergration_test/images/rde_splash_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/inspector_intergration_test/images/rde_splash_sd.jpg +0 -0
- data/intergration/roku_builder/test_files/inspector_intergration_test/images/rsgde_bg_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/inspector_intergration_test/images/rsgde_mm_focus_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/inspector_intergration_test/images/rsgde_splash_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/inspector_intergration_test/manifest +21 -0
- data/intergration/roku_builder/test_files/inspector_intergration_test/source/main.brs +23 -0
- data/intergration/roku_builder/test_files/inspector_intergration_test/test.pkg +0 -0
- data/intergration/roku_builder/test_files/linker_intergration_test/components/rectanglescene.xml +29 -0
- data/intergration/roku_builder/test_files/linker_intergration_test/images/rde_mm_focus_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/linker_intergration_test/images/rde_mm_focus_sd.jpg +0 -0
- data/intergration/roku_builder/test_files/linker_intergration_test/images/rde_splash_fhd.jpg +0 -0
- data/intergration/roku_builder/test_files/linker_intergration_test/images/rde_splash_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/linker_intergration_test/images/rde_splash_sd.jpg +0 -0
- data/intergration/roku_builder/test_files/linker_intergration_test/images/rsgde_bg_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/linker_intergration_test/images/rsgde_mm_focus_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/linker_intergration_test/images/rsgde_splash_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/linker_intergration_test/manifest +21 -0
- data/intergration/roku_builder/test_files/linker_intergration_test/source/main.brs +21 -0
- data/intergration/roku_builder/test_files/linker_intergration_test/test.pkg +0 -0
- data/intergration/roku_builder/test_files/loader_intergration_test/components/rectanglescene.xml +29 -0
- data/intergration/roku_builder/test_files/loader_intergration_test/images/rde_mm_focus_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/loader_intergration_test/images/rde_mm_focus_sd.jpg +0 -0
- data/intergration/roku_builder/test_files/loader_intergration_test/images/rde_splash_fhd.jpg +0 -0
- data/intergration/roku_builder/test_files/loader_intergration_test/images/rde_splash_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/loader_intergration_test/images/rde_splash_sd.jpg +0 -0
- data/intergration/roku_builder/test_files/loader_intergration_test/images/rsgde_bg_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/loader_intergration_test/images/rsgde_mm_focus_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/loader_intergration_test/images/rsgde_splash_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/loader_intergration_test/manifest +21 -0
- data/intergration/roku_builder/test_files/loader_intergration_test/source/main.brs +21 -0
- data/intergration/roku_builder/test_files/loader_intergration_test/test.pkg +0 -0
- data/intergration/roku_builder/test_files/monitor_intergration_test/components/rectanglescene.xml +29 -0
- data/intergration/roku_builder/test_files/monitor_intergration_test/images/rde_mm_focus_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/monitor_intergration_test/images/rde_mm_focus_sd.jpg +0 -0
- data/intergration/roku_builder/test_files/monitor_intergration_test/images/rde_splash_fhd.jpg +0 -0
- data/intergration/roku_builder/test_files/monitor_intergration_test/images/rde_splash_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/monitor_intergration_test/images/rde_splash_sd.jpg +0 -0
- data/intergration/roku_builder/test_files/monitor_intergration_test/images/rsgde_bg_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/monitor_intergration_test/images/rsgde_mm_focus_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/monitor_intergration_test/images/rsgde_splash_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/monitor_intergration_test/manifest +21 -0
- data/intergration/roku_builder/test_files/monitor_intergration_test/source/main.brs +21 -0
- data/intergration/roku_builder/test_files/monitor_intergration_test/test.pkg +0 -0
- data/intergration/roku_builder/test_files/navigator_intergration_test/components/rectanglescene.xml +29 -0
- data/intergration/roku_builder/test_files/navigator_intergration_test/images/rde_mm_focus_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/navigator_intergration_test/images/rde_mm_focus_sd.jpg +0 -0
- data/intergration/roku_builder/test_files/navigator_intergration_test/images/rde_splash_fhd.jpg +0 -0
- data/intergration/roku_builder/test_files/navigator_intergration_test/images/rde_splash_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/navigator_intergration_test/images/rde_splash_sd.jpg +0 -0
- data/intergration/roku_builder/test_files/navigator_intergration_test/images/rsgde_bg_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/navigator_intergration_test/images/rsgde_mm_focus_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/navigator_intergration_test/images/rsgde_splash_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/navigator_intergration_test/manifest +21 -0
- data/intergration/roku_builder/test_files/navigator_intergration_test/source/main.brs +21 -0
- data/intergration/roku_builder/test_files/navigator_intergration_test/test.pkg +0 -0
- data/intergration/roku_builder/test_files/packager_intergration_test/components/rectanglescene.xml +29 -0
- data/intergration/roku_builder/test_files/packager_intergration_test/images/rde_mm_focus_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/packager_intergration_test/images/rde_mm_focus_sd.jpg +0 -0
- data/intergration/roku_builder/test_files/packager_intergration_test/images/rde_splash_fhd.jpg +0 -0
- data/intergration/roku_builder/test_files/packager_intergration_test/images/rde_splash_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/packager_intergration_test/images/rde_splash_sd.jpg +0 -0
- data/intergration/roku_builder/test_files/packager_intergration_test/images/rsgde_bg_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/packager_intergration_test/images/rsgde_mm_focus_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/packager_intergration_test/images/rsgde_splash_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/packager_intergration_test/manifest +21 -0
- data/intergration/roku_builder/test_files/packager_intergration_test/source/main.brs +21 -0
- data/intergration/roku_builder/test_files/packager_intergration_test/test.pkg +0 -0
- data/intergration/roku_builder/test_files/profiler_intergration_test/components/rectanglescene.xml +29 -0
- data/intergration/roku_builder/test_files/profiler_intergration_test/images/rde_mm_focus_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/profiler_intergration_test/images/rde_mm_focus_sd.jpg +0 -0
- data/intergration/roku_builder/test_files/profiler_intergration_test/images/rde_splash_fhd.jpg +0 -0
- data/intergration/roku_builder/test_files/profiler_intergration_test/images/rde_splash_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/profiler_intergration_test/images/rde_splash_sd.jpg +0 -0
- data/intergration/roku_builder/test_files/profiler_intergration_test/images/rsgde_bg_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/profiler_intergration_test/images/rsgde_mm_focus_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/profiler_intergration_test/images/rsgde_splash_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/profiler_intergration_test/manifest +21 -0
- data/intergration/roku_builder/test_files/profiler_intergration_test/source/main.brs +21 -0
- data/intergration/roku_builder/test_files/profiler_intergration_test/test.pkg +0 -0
- data/intergration/roku_builder/test_files/scripter_intergration_test/components/rectanglescene.xml +29 -0
- data/intergration/roku_builder/test_files/scripter_intergration_test/images/rde_mm_focus_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/scripter_intergration_test/images/rde_mm_focus_sd.jpg +0 -0
- data/intergration/roku_builder/test_files/scripter_intergration_test/images/rde_splash_fhd.jpg +0 -0
- data/intergration/roku_builder/test_files/scripter_intergration_test/images/rde_splash_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/scripter_intergration_test/images/rde_splash_sd.jpg +0 -0
- data/intergration/roku_builder/test_files/scripter_intergration_test/images/rsgde_bg_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/scripter_intergration_test/images/rsgde_mm_focus_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/scripter_intergration_test/images/rsgde_splash_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/scripter_intergration_test/manifest +21 -0
- data/intergration/roku_builder/test_files/scripter_intergration_test/source/main.brs +21 -0
- data/intergration/roku_builder/test_files/scripter_intergration_test/test.pkg +0 -0
- data/intergration/roku_builder/test_files/tester_intergration_test/components/rectanglescene.xml +29 -0
- data/intergration/roku_builder/test_files/tester_intergration_test/images/rde_mm_focus_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/tester_intergration_test/images/rde_mm_focus_sd.jpg +0 -0
- data/intergration/roku_builder/test_files/tester_intergration_test/images/rde_splash_fhd.jpg +0 -0
- data/intergration/roku_builder/test_files/tester_intergration_test/images/rde_splash_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/tester_intergration_test/images/rde_splash_sd.jpg +0 -0
- data/intergration/roku_builder/test_files/tester_intergration_test/images/rsgde_bg_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/tester_intergration_test/images/rsgde_mm_focus_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/tester_intergration_test/images/rsgde_splash_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/tester_intergration_test/manifest +21 -0
- data/intergration/roku_builder/test_files/tester_intergration_test/source/main.brs +21 -0
- data/intergration/roku_builder/test_files/tester_intergration_test/test.pkg +0 -0
- data/intergration/roku_builder/test_helper.rb +138 -0
- data/intergration/roku_builder/test_inspector.rb +35 -0
- data/intergration/roku_builder/test_linker.rb +32 -0
- data/intergration/roku_builder/test_loader.rb +38 -0
- data/intergration/roku_builder/test_monitor.rb +21 -0
- data/intergration/roku_builder/test_navigator.rb +34 -0
- data/intergration/roku_builder/test_packager.rb +41 -0
- data/intergration/roku_builder/test_profiler.rb +48 -0
- data/intergration/roku_builder/test_scripter.rb +38 -0
- data/intergration/roku_builder/test_tester.rb +21 -0
- data/lib/roku_builder.rb +143 -154
- data/lib/roku_builder/config.rb +17 -40
- data/lib/roku_builder/config_parser.rb +49 -200
- data/lib/roku_builder/config_validator.rb +1 -1
- data/lib/roku_builder/errors.rb +12 -0
- data/lib/roku_builder/git.rb +28 -0
- data/lib/roku_builder/hash.rb +8 -0
- data/lib/roku_builder/manifest.rb +121 -0
- data/lib/roku_builder/options.rb +68 -29
- data/lib/roku_builder/plugin.rb +30 -0
- data/lib/roku_builder/plugins/core.rb +117 -0
- data/lib/roku_builder/plugins/inspector.rb +104 -0
- data/lib/roku_builder/{linker.rb → plugins/linker.rb} +38 -12
- data/lib/roku_builder/plugins/loader.rb +152 -0
- data/lib/roku_builder/{monitor.rb → plugins/monitor.rb} +20 -9
- data/lib/roku_builder/{navigator.rb → plugins/navigator.rb} +136 -88
- data/lib/roku_builder/plugins/packager.rb +194 -0
- data/lib/roku_builder/plugins/profiler.rb +135 -0
- data/lib/roku_builder/plugins/scripter.rb +53 -0
- data/lib/roku_builder/{tester.rb → plugins/tester.rb} +28 -19
- data/lib/roku_builder/stager.rb +48 -12
- data/lib/roku_builder/string.rb +20 -0
- data/lib/roku_builder/util.rb +10 -34
- data/lib/roku_builder/version.rb +1 -1
- data/rakefile +5 -1
- data/roku_builder.gemspec +2 -0
- data/test/roku_builder/plugins/test_core.rb +112 -0
- data/test/roku_builder/plugins/test_inspector.rb +165 -0
- data/test/roku_builder/plugins/test_linker.rb +123 -0
- data/test/roku_builder/plugins/test_loader.rb +115 -0
- data/test/roku_builder/plugins/test_monitor.rb +141 -0
- data/test/roku_builder/plugins/test_navigator.rb +274 -0
- data/test/roku_builder/plugins/test_packager.rb +202 -0
- data/test/roku_builder/plugins/test_profiler.rb +127 -0
- data/test/roku_builder/plugins/test_scripter.rb +110 -0
- data/test/roku_builder/plugins/test_tester.rb +109 -0
- data/test/roku_builder/test_config.rb +51 -35
- data/test/roku_builder/test_config_parser.rb +76 -154
- data/test/roku_builder/test_config_validator.rb +18 -1
- data/test/roku_builder/test_files/{loader_test/manifest → config_parser_test/test.pkg} +0 -0
- data/test/roku_builder/test_files/config_test/config.json +3 -0
- data/test/roku_builder/test_files/controller_commands_test/manifest_template +7 -0
- data/test/roku_builder/test_files/core_test/manifest_template +7 -0
- data/test/roku_builder/test_files/core_test/test.pkg +0 -0
- data/test/roku_builder/test_files/inspector_test/manifest +6 -0
- data/test/roku_builder/test_files/inspector_test/test.pkg +0 -0
- data/test/roku_builder/test_files/linker_test/manifest +6 -0
- data/test/roku_builder/test_files/linker_test/test.pkg +0 -0
- data/test/roku_builder/test_files/loader_test/manifest_template +6 -0
- data/test/roku_builder/test_files/loader_test/test.pkg +0 -0
- data/test/roku_builder/test_files/loader_test/test.zip +0 -0
- data/test/roku_builder/test_files/manifest_test/manifest_comments +6 -0
- data/test/roku_builder/test_files/manifest_test/manifest_template +7 -0
- data/test/roku_builder/test_files/manifest_test/test.zip +0 -0
- data/test/roku_builder/test_files/packager_test/manifest +6 -0
- data/test/roku_builder/test_files/packager_test/scripter_test/manifest +6 -0
- data/test/roku_builder/test_files/packager_test/test.pkg +0 -0
- data/test/roku_builder/test_files/roku_builder_test/config.json +32 -0
- data/test/roku_builder/test_files/scripter_test/manifest +6 -0
- data/test/roku_builder/test_files/scripter_test/test.pkg +0 -0
- data/test/roku_builder/test_files/stager_test/test.pkg +0 -0
- data/test/roku_builder/test_files/tester_test/manifest +6 -0
- data/test/roku_builder/test_files/tester_test/test.pkg +0 -0
- data/test/roku_builder/test_helper.rb +44 -11
- data/test/roku_builder/test_logger.rb +1 -0
- data/test/roku_builder/test_manifest.rb +99 -0
- data/test/roku_builder/test_options.rb +106 -77
- data/test/roku_builder/test_options_plugins.rb +111 -0
- data/test/roku_builder/test_plugin.rb +48 -0
- data/test/roku_builder/test_roku_builder.rb +239 -0
- data/test/roku_builder/test_stager.rb +49 -101
- data/test/roku_builder/test_util.rb +19 -4
- metadata +241 -47
- data/lib/roku_builder/controller.rb +0 -98
- data/lib/roku_builder/controller_commands.rb +0 -224
- data/lib/roku_builder/error_handler.rb +0 -142
- data/lib/roku_builder/inspector.rb +0 -82
- data/lib/roku_builder/keyer.rb +0 -106
- data/lib/roku_builder/loader.rb +0 -131
- data/lib/roku_builder/manifest_manager.rb +0 -126
- data/lib/roku_builder/packager.rb +0 -43
- data/lib/roku_builder/profiler.rb +0 -96
- data/lib/roku_builder/scripter.rb +0 -39
- data/test/roku_builder/test_controller.rb +0 -70
- data/test/roku_builder/test_controller_commands.rb +0 -465
- data/test/roku_builder/test_error_handler.rb +0 -90
- data/test/roku_builder/test_inspector.rb +0 -298
- data/test/roku_builder/test_keyer.rb +0 -176
- data/test/roku_builder/test_linker.rb +0 -110
- data/test/roku_builder/test_loader.rb +0 -337
- data/test/roku_builder/test_manifest_manager.rb +0 -103
- data/test/roku_builder/test_monitor.rb +0 -137
- data/test/roku_builder/test_navigator.rb +0 -280
- data/test/roku_builder/test_packager.rb +0 -127
- data/test/roku_builder/test_profiler.rb +0 -35
- data/test/roku_builder/test_scripter.rb +0 -102
- data/test/roku_builder/test_tester.rb +0 -130
data/lib/roku_builder/keyer.rb
DELETED
@@ -1,106 +0,0 @@
|
|
1
|
-
# ********** Copyright Viacom, Inc. Apache 2.0 **********
|
2
|
-
|
3
|
-
module RokuBuilder
|
4
|
-
|
5
|
-
# Change or get dev key
|
6
|
-
class Keyer < Util
|
7
|
-
|
8
|
-
def genkey(out_file: nil)
|
9
|
-
password, dev_id = generate_new_key()
|
10
|
-
@logger.unknown("Password: "+password)
|
11
|
-
@logger.info("DevID: "+dev_id)
|
12
|
-
|
13
|
-
unless out_file
|
14
|
-
out_file = File.join(Dir.tmpdir, "key_"+dev_id+".pkg")
|
15
|
-
end
|
16
|
-
|
17
|
-
Dir.mktmpdir { |dir|
|
18
|
-
ManifestManager.update_manifest({root_dir: dir, attributes: {}})
|
19
|
-
Dir.mkdir(File.join(dir, "source"))
|
20
|
-
File.open(File.join(dir, "source", "main.brs"), "w") do |io|
|
21
|
-
io.puts "sub main()"
|
22
|
-
io.puts " print \"Load\""
|
23
|
-
io.puts "end sub"
|
24
|
-
end
|
25
|
-
@device_config[:init_params] = {root_dir: dir}
|
26
|
-
loader = Loader.new(**@device_config)
|
27
|
-
loader.sideload()
|
28
|
-
@device_config.delete(:init_params)
|
29
|
-
packager = Packager.new(**@device_config)
|
30
|
-
packager.package(app_name_version: "key_"+dev_id, out_file: out_file, password: password)
|
31
|
-
@logger.unknown("Keyed PKG: "+out_file)
|
32
|
-
}
|
33
|
-
end
|
34
|
-
|
35
|
-
# Sets the key on the roku device
|
36
|
-
# @param keyed_pkg [String] Path for a package signed with the desired key
|
37
|
-
# @param password [String] Password for the package
|
38
|
-
# @return [Boolean] True if key changed, false otherwise
|
39
|
-
def rekey(keyed_pkg:, password:)
|
40
|
-
oldId = dev_id
|
41
|
-
|
42
|
-
# upload new key with password
|
43
|
-
path = "/plugin_inspect"
|
44
|
-
conn = multipart_connection
|
45
|
-
payload = {
|
46
|
-
mysubmit: "Rekey",
|
47
|
-
passwd: password,
|
48
|
-
archive: Faraday::UploadIO.new(keyed_pkg, 'application/octet-stream')
|
49
|
-
}
|
50
|
-
conn.post path, payload
|
51
|
-
|
52
|
-
# check key
|
53
|
-
newId = dev_id
|
54
|
-
@logger.info("Key did not change") unless newId != oldId
|
55
|
-
@logger.debug(oldId + " -> " + newId)
|
56
|
-
newId != oldId
|
57
|
-
end
|
58
|
-
|
59
|
-
# Get the current dev id
|
60
|
-
# @return [String] The current dev id
|
61
|
-
def dev_id
|
62
|
-
path = "/plugin_package"
|
63
|
-
conn = simple_connection
|
64
|
-
response = conn.get path
|
65
|
-
|
66
|
-
dev_id = /Your Dev ID:\s*<font[^>]*>([^<]*)<\/font>/.match(response.body)
|
67
|
-
dev_id ||= /Your Dev ID:[^>]*<\/label> ([^<]*)/.match(response.body)
|
68
|
-
dev_id = dev_id[1] if dev_id
|
69
|
-
dev_id ||= "none"
|
70
|
-
dev_id
|
71
|
-
end
|
72
|
-
|
73
|
-
private
|
74
|
-
|
75
|
-
# Uses the device to generate a new signing key
|
76
|
-
# @return [Array<String>] Password and dev_id for the new key
|
77
|
-
def generate_new_key()
|
78
|
-
telnet_config = {
|
79
|
-
'Host' => @roku_ip_address,
|
80
|
-
'Port' => 8080
|
81
|
-
}
|
82
|
-
connection = Net::Telnet.new(telnet_config)
|
83
|
-
connection.puts("genkey")
|
84
|
-
waitfor_config = {
|
85
|
-
'Match' => /./,
|
86
|
-
'Timeout' => false
|
87
|
-
}
|
88
|
-
password = nil
|
89
|
-
dev_id = nil
|
90
|
-
while password.nil? or dev_id.nil?
|
91
|
-
connection.waitfor(waitfor_config) do |txt|
|
92
|
-
while line = txt.slice!(/^.*\n/) do
|
93
|
-
words = line.split
|
94
|
-
if words[0] == "Password:"
|
95
|
-
password = words[1]
|
96
|
-
elsif words[0] == "DevID:"
|
97
|
-
dev_id = words[1]
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
102
|
-
connection.close
|
103
|
-
return password, dev_id
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
data/lib/roku_builder/loader.rb
DELETED
@@ -1,131 +0,0 @@
|
|
1
|
-
# ********** Copyright Viacom, Inc. Apache 2.0 **********
|
2
|
-
|
3
|
-
module RokuBuilder
|
4
|
-
|
5
|
-
# Load/Unload/Build roku applications
|
6
|
-
class Loader < Util
|
7
|
-
|
8
|
-
|
9
|
-
# Set the root directory
|
10
|
-
def init(root_dir: nil)
|
11
|
-
@root_dir = root_dir
|
12
|
-
end
|
13
|
-
|
14
|
-
# Sideload an app onto a roku device
|
15
|
-
# @param root_dir [String] Path to the root directory of the roku app
|
16
|
-
# @param content [Hash] Hash containing arrays for folder, files, and excludes. Default: nil
|
17
|
-
# @return [String] Build version on success, nil otherwise
|
18
|
-
def sideload(update_manifest: false, content: nil, infile: nil, out_file: nil)
|
19
|
-
Navigator.new(**@device_config).nav(commands: [:home])
|
20
|
-
result = FAILED_SIDELOAD
|
21
|
-
build_version = nil
|
22
|
-
if infile
|
23
|
-
build_version = ManifestManager.build_version(root_dir: infile)
|
24
|
-
out_file = infile
|
25
|
-
else
|
26
|
-
# Update manifest
|
27
|
-
if update_manifest
|
28
|
-
build_version = ManifestManager.update_build(root_dir: @root_dir)
|
29
|
-
else
|
30
|
-
build_version = ManifestManager.build_version(root_dir: @root_dir)
|
31
|
-
end
|
32
|
-
@logger.info "Build: #{out_file}" if out_file
|
33
|
-
out_file = build(build_version: build_version, out_file: out_file, content: content)
|
34
|
-
end
|
35
|
-
return [MISSING_MANIFEST, nil] if out_file == MISSING_MANIFEST
|
36
|
-
path = "/plugin_install"
|
37
|
-
# Connect to roku and upload file
|
38
|
-
conn = multipart_connection
|
39
|
-
payload = {
|
40
|
-
mysubmit: "Replace",
|
41
|
-
archive: Faraday::UploadIO.new(out_file, 'application/zip')
|
42
|
-
}
|
43
|
-
response = conn.post path, payload
|
44
|
-
# Cleanup
|
45
|
-
File.delete(out_file) if infile.nil? and out_file.nil?
|
46
|
-
result = SUCCESS if response.status==200 and response.body=~/Install Success/
|
47
|
-
result = IDENTICAL_SIDELOAD if response.status==200 and response.body=~/Identical to previous version/
|
48
|
-
[result, build_version]
|
49
|
-
end
|
50
|
-
|
51
|
-
|
52
|
-
# Build an app to sideload later
|
53
|
-
# @param root_dir [String] Path to the root directory of the roku app
|
54
|
-
# @param build_version [String] Version to assigne to the build. If nil will pull the build version form the manifest. Default: nil
|
55
|
-
# @param out_file [String] Path for the output file. If nil will create a file in /tmp. Default: nil
|
56
|
-
# @param content [Hash] Hash containing arrays for folder, files, and excludes. Default: nil
|
57
|
-
# @return [String] Path of the build
|
58
|
-
def build(build_version: nil, out_file: nil, content: nil)
|
59
|
-
build_version = ManifestManager.build_version(root_dir: @root_dir) unless build_version
|
60
|
-
return MISSING_MANIFEST if build_version == MISSING_MANIFEST
|
61
|
-
content ||= {}
|
62
|
-
content[:folders] ||= Dir.entries(@root_dir).select {|entry| File.directory? File.join(@root_dir, entry) and !(entry =='.' || entry == '..') }
|
63
|
-
content[:files] ||= Dir.entries(@root_dir).select {|entry| File.file? File.join(@root_dir, entry)}
|
64
|
-
content[:excludes] ||= []
|
65
|
-
out_file = "#{Dir.tmpdir}/#{build_version}" unless out_file
|
66
|
-
out_file = out_file+".zip" unless out_file.end_with?(".zip")
|
67
|
-
File.delete(out_file) if File.exist?(out_file)
|
68
|
-
io = Zip::File.open(out_file, Zip::File::CREATE)
|
69
|
-
# Add folders to zip
|
70
|
-
content[:folders].each do |folder|
|
71
|
-
base_folder = File.join(@root_dir, folder)
|
72
|
-
if File.exist?(base_folder)
|
73
|
-
entries = Dir.entries(base_folder)
|
74
|
-
entries.delete(".")
|
75
|
-
entries.delete("..")
|
76
|
-
writeEntries(@root_dir, entries, folder, content[:excludes], io)
|
77
|
-
else
|
78
|
-
@logger.warn "Missing Folder: #{base_folder}"
|
79
|
-
end
|
80
|
-
end
|
81
|
-
# Add file to zip
|
82
|
-
writeEntries(@root_dir, content[:files], "", content[:excludes], io)
|
83
|
-
io.close()
|
84
|
-
out_file
|
85
|
-
end
|
86
|
-
|
87
|
-
# Remove the currently sideloaded app
|
88
|
-
def unload()
|
89
|
-
path = "/plugin_install"
|
90
|
-
|
91
|
-
# Connect to roku and upload file
|
92
|
-
conn = multipart_connection
|
93
|
-
payload = {
|
94
|
-
mysubmit: "Delete",
|
95
|
-
archive: ""
|
96
|
-
}
|
97
|
-
response = conn.post path, payload
|
98
|
-
if response.status == 200 and response.body =~ /Install Success/
|
99
|
-
return true
|
100
|
-
end
|
101
|
-
return false
|
102
|
-
end
|
103
|
-
|
104
|
-
private
|
105
|
-
|
106
|
-
# Recursively write directory contents to a zip archive
|
107
|
-
# @param root_dir [String] Path of the root directory
|
108
|
-
# @param entries [Array<String>] Array of file paths of files/directories to store in the zip archive
|
109
|
-
# @param path [String] The path of the current directory starting at the root directory
|
110
|
-
# @param io [IO] zip IO object
|
111
|
-
def writeEntries(root_dir, entries, path, excludes, io)
|
112
|
-
entries.each { |e|
|
113
|
-
zipFilePath = path == "" ? e : File.join(path, e)
|
114
|
-
diskFilePath = File.join(root_dir, zipFilePath)
|
115
|
-
if File.directory?(diskFilePath)
|
116
|
-
io.mkdir(zipFilePath)
|
117
|
-
subdir =Dir.entries(diskFilePath); subdir.delete("."); subdir.delete("..")
|
118
|
-
writeEntries(root_dir, subdir, zipFilePath, excludes, io)
|
119
|
-
else
|
120
|
-
unless excludes.include?(zipFilePath)
|
121
|
-
if File.exist?(diskFilePath)
|
122
|
-
io.get_output_stream(zipFilePath) { |f| f.puts(File.open(diskFilePath, "rb").read()) }
|
123
|
-
else
|
124
|
-
@logger.warn "Missing File: #{diskFilePath}"
|
125
|
-
end
|
126
|
-
end
|
127
|
-
end
|
128
|
-
}
|
129
|
-
end
|
130
|
-
end
|
131
|
-
end
|
@@ -1,126 +0,0 @@
|
|
1
|
-
# ********** Copyright Viacom, Inc. Apache 2.0 **********
|
2
|
-
|
3
|
-
module RokuBuilder
|
4
|
-
|
5
|
-
# Updates or retrives build version
|
6
|
-
class ManifestManager
|
7
|
-
|
8
|
-
# Updates the build version in the manifest file
|
9
|
-
# @param root_dir [String] Path to the root directory for the app
|
10
|
-
# @return [String] Build version on success, empty string otherwise
|
11
|
-
def self.update_build(root_dir:)
|
12
|
-
return MISSING_MANIFEST unless self.check_manifest(root_dir: root_dir)
|
13
|
-
build_version = self.build_version(root_dir: root_dir).split(".")
|
14
|
-
if 2 == build_version.length
|
15
|
-
iteration = build_version[1].to_i + 1
|
16
|
-
build_version[0] = Time.now.strftime("%m%d%y")
|
17
|
-
build_version[1] = iteration
|
18
|
-
build_version = build_version.join(".")
|
19
|
-
else
|
20
|
-
iteration = build_version[0].to_i + 1
|
21
|
-
build_version = iteration.to_s
|
22
|
-
end
|
23
|
-
self.update_manifest(root_dir: root_dir, attributes: {build_version: build_version})
|
24
|
-
self.build_version(root_dir: root_dir)
|
25
|
-
end
|
26
|
-
|
27
|
-
|
28
|
-
# Retrive the build version from the manifest file
|
29
|
-
# @param root_dir [String] Path to the root directory for the app
|
30
|
-
# @return [String] Build version on success, empty string otherwise
|
31
|
-
def self.build_version(root_dir:)
|
32
|
-
return MISSING_MANIFEST unless self.check_manifest(root_dir: root_dir)
|
33
|
-
read_manifest(root_dir: root_dir)[:build_version]
|
34
|
-
end
|
35
|
-
|
36
|
-
def self.read_manifest(root_dir:)
|
37
|
-
return MISSING_MANIFEST unless self.check_manifest(root_dir: root_dir)
|
38
|
-
attrs = {}
|
39
|
-
get_attrs = lambda { |file|
|
40
|
-
file.each_line do |line|
|
41
|
-
key, value = line.split("=")
|
42
|
-
if value
|
43
|
-
attrs[key.chomp.to_sym]= value.chomp
|
44
|
-
elsif key and !key.chomp.empty?
|
45
|
-
attrs[key.chomp.to_sym]= nil
|
46
|
-
end
|
47
|
-
end
|
48
|
-
}
|
49
|
-
if File.directory?(root_dir)
|
50
|
-
path = File.join(root_dir, 'manifest')
|
51
|
-
File.open(path, 'r', &get_attrs)
|
52
|
-
elsif File.extname(root_dir) == ".zip"
|
53
|
-
Zip::File.open(root_dir) do |zip_file|
|
54
|
-
entry = zip_file.glob("manifest").first
|
55
|
-
entry.get_input_stream(&get_attrs)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
attrs
|
59
|
-
end
|
60
|
-
|
61
|
-
# Update attributes in the app manifest
|
62
|
-
# It will add missing attributes but not remove them
|
63
|
-
# @param root_dir [String] The app root directory
|
64
|
-
# @param attributes [Hash] The new attributes for the app manifest
|
65
|
-
def self.update_manifest(root_dir:, attributes:, set_default: true)
|
66
|
-
temp_file = Tempfile.new('manifest')
|
67
|
-
path = File.join(root_dir, 'manifest')
|
68
|
-
new_params = attributes.dup
|
69
|
-
begin
|
70
|
-
if File.exist?(path)
|
71
|
-
File.open(path, 'r') do |file|
|
72
|
-
file.each_line do |line|
|
73
|
-
key = line.split("=")[0]
|
74
|
-
if new_params.include?(key.to_sym)
|
75
|
-
temp_file.puts("#{key}=#{new_params[key.to_sym]}")
|
76
|
-
new_params.delete(key.to_sym)
|
77
|
-
else
|
78
|
-
temp_file.puts(line)
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
82
|
-
elsif set_default
|
83
|
-
new_params = self.default_params().merge(new_params)
|
84
|
-
end
|
85
|
-
new_params.each_pair do |key, value|
|
86
|
-
temp_file.puts("#{key}=#{value}")
|
87
|
-
end
|
88
|
-
temp_file.rewind
|
89
|
-
FileUtils.cp(temp_file.path, path)
|
90
|
-
ensure
|
91
|
-
temp_file.close
|
92
|
-
temp_file.unlink
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
# Check to make sure that the manifest file exists
|
97
|
-
# @param root_dir [String] Path to the root directory for the app
|
98
|
-
# @return [Boolean] True if manifest exists, false otherwise
|
99
|
-
def self.check_manifest(root_dir:)
|
100
|
-
return false unless File.exist?(root_dir)
|
101
|
-
if File.directory?(root_dir)
|
102
|
-
path = File.join(root_dir, 'manifest')
|
103
|
-
return false unless File.exist?(path)
|
104
|
-
elsif File.extname(root_dir) == ".zip"
|
105
|
-
Zip::File.open(root_dir) do |zip_file|
|
106
|
-
entry = zip_file.glob("manifest").first
|
107
|
-
return false unless entry
|
108
|
-
end
|
109
|
-
end
|
110
|
-
true
|
111
|
-
end
|
112
|
-
|
113
|
-
# Returns the default manafest values
|
114
|
-
# @return [Hash] default manifest values
|
115
|
-
def self.default_params
|
116
|
-
{
|
117
|
-
title: "Default Title",
|
118
|
-
major_version: 1,
|
119
|
-
minor_version: 0,
|
120
|
-
build_version: "010101.0001",
|
121
|
-
mm_icon_focus_hd: "<insert hd focus icon url>",
|
122
|
-
mm_icon_focus_sd: "<insert sd focus icon url>"
|
123
|
-
}
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|
@@ -1,43 +0,0 @@
|
|
1
|
-
# ********** Copyright Viacom, Inc. Apache 2.0 **********
|
2
|
-
|
3
|
-
module RokuBuilder
|
4
|
-
|
5
|
-
# Method of packaging app for submission
|
6
|
-
class Packager < Util
|
7
|
-
|
8
|
-
# Sign and download the currently sideloaded app
|
9
|
-
# @param app_name_version [String] The name and version of the package
|
10
|
-
# @param out_file [String] Location to download signed package to
|
11
|
-
# @param password [String] Password for the devices current key
|
12
|
-
# @return [Boolean] True on package success and download, false otherwise
|
13
|
-
def package(app_name_version:, out_file:, password:)
|
14
|
-
# Sign package
|
15
|
-
path = "/plugin_package"
|
16
|
-
conn = multipart_connection
|
17
|
-
payload = {
|
18
|
-
mysubmit: "Package",
|
19
|
-
app_name: app_name_version,
|
20
|
-
passwd: password,
|
21
|
-
pkg_time: Time.now.to_i
|
22
|
-
}
|
23
|
-
response = conn.post path, payload
|
24
|
-
|
25
|
-
# Check for error
|
26
|
-
failed = /(Failed: [^\.]*\.)/.match(response.body)
|
27
|
-
return failed[1] if failed
|
28
|
-
|
29
|
-
# Download signed package
|
30
|
-
pkg = /<a href="pkgs[^>]*>([^<]*)</.match(response.body)[1]
|
31
|
-
path = "/pkgs/#{pkg}"
|
32
|
-
conn = Faraday.new(url: @url) do |f|
|
33
|
-
f.request :digest, @dev_username, @dev_password
|
34
|
-
f.adapter Faraday.default_adapter
|
35
|
-
end
|
36
|
-
response = conn.get path
|
37
|
-
return false if response.status != 200
|
38
|
-
out_file = out_file+".pkg" unless out_file.end_with?(".pkg")
|
39
|
-
File.open(out_file, 'w+') {|fp| fp.write(response.body)}
|
40
|
-
true
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
@@ -1,96 +0,0 @@
|
|
1
|
-
# ********** Copyright Viacom, Inc. Apache 2.0 **********
|
2
|
-
|
3
|
-
module RokuBuilder
|
4
|
-
|
5
|
-
# Scene Graph Profiler
|
6
|
-
class Profiler < Util
|
7
|
-
|
8
|
-
# Run the profiler commands
|
9
|
-
# @param command [Symbol] The profiler command to run
|
10
|
-
def run(command:)
|
11
|
-
case command
|
12
|
-
when :stats
|
13
|
-
print_stats
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
private
|
18
|
-
|
19
|
-
# Print the node stats
|
20
|
-
def print_stats
|
21
|
-
lines = get_all_nodes
|
22
|
-
xml_string = lines.join("\n")
|
23
|
-
stats = {"Total" => 0}
|
24
|
-
doc = Nokogiri::XML(xml_string)
|
25
|
-
handle_node(stats: stats, node: doc.root)
|
26
|
-
stats = stats.to_a
|
27
|
-
stats = stats.sort {|a, b| b[1] <=> a[1]}
|
28
|
-
printf "%30s | %5s\n", "Name", "Count"
|
29
|
-
stats.each do |key_pair|
|
30
|
-
printf "%30s | %5d\n", key_pair[0], key_pair[1]
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def handle_node(stats:, node:)
|
35
|
-
node.element_children.each do |element|
|
36
|
-
stats[element.name] ||= 0
|
37
|
-
stats[element.name] += 1
|
38
|
-
stats["Total"] += 1
|
39
|
-
handle_node(stats: stats, node: element)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
# Retrive list of all nodes
|
44
|
-
# @return [Array<String>] Array of lines
|
45
|
-
def get_all_nodes
|
46
|
-
waitfor_config = {
|
47
|
-
'Match' => /.+/,
|
48
|
-
'Timeout' => 5
|
49
|
-
}
|
50
|
-
telnet_config ={
|
51
|
-
'Host' => @roku_ip_address,
|
52
|
-
'Port' => 8080
|
53
|
-
}
|
54
|
-
|
55
|
-
connection = Net::Telnet.new(telnet_config)
|
56
|
-
|
57
|
-
lines = []
|
58
|
-
all_txt = ""
|
59
|
-
in_nodes = false
|
60
|
-
done = false
|
61
|
-
connection.puts("sgnodes all\n")
|
62
|
-
while not done
|
63
|
-
begin
|
64
|
-
connection.waitfor(waitfor_config) do |txt|
|
65
|
-
in_nodes, done, all_txt = handle_text(all_txt: all_txt, txt: txt, in_nodes: in_nodes, lines: lines)
|
66
|
-
end
|
67
|
-
rescue Net::ReadTimeout
|
68
|
-
@logger.warn "Timed out reading profiler information"
|
69
|
-
done = true
|
70
|
-
end
|
71
|
-
end
|
72
|
-
lines
|
73
|
-
end
|
74
|
-
|
75
|
-
# Handle profiling text
|
76
|
-
# @param all_txt [String] remainder text from last run
|
77
|
-
# @param txt [String] current text from telnet
|
78
|
-
# @param in_nodes [Boolean] currently parsing test text
|
79
|
-
# @return [Boolean] currently parsing test text
|
80
|
-
def handle_text(all_txt:, txt:, in_nodes:, lines:)
|
81
|
-
all_txt += txt
|
82
|
-
end_reg = /<\/All_Nodes>/
|
83
|
-
start_reg = /<All_Nodes>/
|
84
|
-
done = false
|
85
|
-
while line = all_txt.slice!(/^.*\n/) do
|
86
|
-
in_nodes = true if line =~ start_reg
|
87
|
-
lines.push(line) if in_nodes
|
88
|
-
if line =~ end_reg
|
89
|
-
in_nodes = false
|
90
|
-
done = true
|
91
|
-
end
|
92
|
-
end
|
93
|
-
[in_nodes, done, all_txt]
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|