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.
Files changed (226) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -1
  3. data/CHANGELOG +12 -0
  4. data/Gemfile.lock +22 -7
  5. data/Guardfile +3 -3
  6. data/README.md +22 -398
  7. data/bin/roku +1 -194
  8. data/config.json.example +1 -1
  9. data/intergration/roku_builder/test_core.rb +52 -0
  10. data/intergration/roku_builder/test_files/core_intergration_test/manifest_template +7 -0
  11. data/intergration/roku_builder/test_files/core_intergration_test/test.pkg +0 -0
  12. data/intergration/roku_builder/test_files/inspector_intergration_test/components/rectanglescene.xml +28 -0
  13. data/intergration/roku_builder/test_files/inspector_intergration_test/images/rde_mm_focus_hd.jpg +0 -0
  14. data/intergration/roku_builder/test_files/inspector_intergration_test/images/rde_mm_focus_sd.jpg +0 -0
  15. data/intergration/roku_builder/test_files/inspector_intergration_test/images/rde_splash_fhd.jpg +0 -0
  16. data/intergration/roku_builder/test_files/inspector_intergration_test/images/rde_splash_hd.jpg +0 -0
  17. data/intergration/roku_builder/test_files/inspector_intergration_test/images/rde_splash_sd.jpg +0 -0
  18. data/intergration/roku_builder/test_files/inspector_intergration_test/images/rsgde_bg_hd.jpg +0 -0
  19. data/intergration/roku_builder/test_files/inspector_intergration_test/images/rsgde_mm_focus_hd.jpg +0 -0
  20. data/intergration/roku_builder/test_files/inspector_intergration_test/images/rsgde_splash_hd.jpg +0 -0
  21. data/intergration/roku_builder/test_files/inspector_intergration_test/manifest +21 -0
  22. data/intergration/roku_builder/test_files/inspector_intergration_test/source/main.brs +23 -0
  23. data/intergration/roku_builder/test_files/inspector_intergration_test/test.pkg +0 -0
  24. data/intergration/roku_builder/test_files/linker_intergration_test/components/rectanglescene.xml +29 -0
  25. data/intergration/roku_builder/test_files/linker_intergration_test/images/rde_mm_focus_hd.jpg +0 -0
  26. data/intergration/roku_builder/test_files/linker_intergration_test/images/rde_mm_focus_sd.jpg +0 -0
  27. data/intergration/roku_builder/test_files/linker_intergration_test/images/rde_splash_fhd.jpg +0 -0
  28. data/intergration/roku_builder/test_files/linker_intergration_test/images/rde_splash_hd.jpg +0 -0
  29. data/intergration/roku_builder/test_files/linker_intergration_test/images/rde_splash_sd.jpg +0 -0
  30. data/intergration/roku_builder/test_files/linker_intergration_test/images/rsgde_bg_hd.jpg +0 -0
  31. data/intergration/roku_builder/test_files/linker_intergration_test/images/rsgde_mm_focus_hd.jpg +0 -0
  32. data/intergration/roku_builder/test_files/linker_intergration_test/images/rsgde_splash_hd.jpg +0 -0
  33. data/intergration/roku_builder/test_files/linker_intergration_test/manifest +21 -0
  34. data/intergration/roku_builder/test_files/linker_intergration_test/source/main.brs +21 -0
  35. data/intergration/roku_builder/test_files/linker_intergration_test/test.pkg +0 -0
  36. data/intergration/roku_builder/test_files/loader_intergration_test/components/rectanglescene.xml +29 -0
  37. data/intergration/roku_builder/test_files/loader_intergration_test/images/rde_mm_focus_hd.jpg +0 -0
  38. data/intergration/roku_builder/test_files/loader_intergration_test/images/rde_mm_focus_sd.jpg +0 -0
  39. data/intergration/roku_builder/test_files/loader_intergration_test/images/rde_splash_fhd.jpg +0 -0
  40. data/intergration/roku_builder/test_files/loader_intergration_test/images/rde_splash_hd.jpg +0 -0
  41. data/intergration/roku_builder/test_files/loader_intergration_test/images/rde_splash_sd.jpg +0 -0
  42. data/intergration/roku_builder/test_files/loader_intergration_test/images/rsgde_bg_hd.jpg +0 -0
  43. data/intergration/roku_builder/test_files/loader_intergration_test/images/rsgde_mm_focus_hd.jpg +0 -0
  44. data/intergration/roku_builder/test_files/loader_intergration_test/images/rsgde_splash_hd.jpg +0 -0
  45. data/intergration/roku_builder/test_files/loader_intergration_test/manifest +21 -0
  46. data/intergration/roku_builder/test_files/loader_intergration_test/source/main.brs +21 -0
  47. data/intergration/roku_builder/test_files/loader_intergration_test/test.pkg +0 -0
  48. data/intergration/roku_builder/test_files/monitor_intergration_test/components/rectanglescene.xml +29 -0
  49. data/intergration/roku_builder/test_files/monitor_intergration_test/images/rde_mm_focus_hd.jpg +0 -0
  50. data/intergration/roku_builder/test_files/monitor_intergration_test/images/rde_mm_focus_sd.jpg +0 -0
  51. data/intergration/roku_builder/test_files/monitor_intergration_test/images/rde_splash_fhd.jpg +0 -0
  52. data/intergration/roku_builder/test_files/monitor_intergration_test/images/rde_splash_hd.jpg +0 -0
  53. data/intergration/roku_builder/test_files/monitor_intergration_test/images/rde_splash_sd.jpg +0 -0
  54. data/intergration/roku_builder/test_files/monitor_intergration_test/images/rsgde_bg_hd.jpg +0 -0
  55. data/intergration/roku_builder/test_files/monitor_intergration_test/images/rsgde_mm_focus_hd.jpg +0 -0
  56. data/intergration/roku_builder/test_files/monitor_intergration_test/images/rsgde_splash_hd.jpg +0 -0
  57. data/intergration/roku_builder/test_files/monitor_intergration_test/manifest +21 -0
  58. data/intergration/roku_builder/test_files/monitor_intergration_test/source/main.brs +21 -0
  59. data/intergration/roku_builder/test_files/monitor_intergration_test/test.pkg +0 -0
  60. data/intergration/roku_builder/test_files/navigator_intergration_test/components/rectanglescene.xml +29 -0
  61. data/intergration/roku_builder/test_files/navigator_intergration_test/images/rde_mm_focus_hd.jpg +0 -0
  62. data/intergration/roku_builder/test_files/navigator_intergration_test/images/rde_mm_focus_sd.jpg +0 -0
  63. data/intergration/roku_builder/test_files/navigator_intergration_test/images/rde_splash_fhd.jpg +0 -0
  64. data/intergration/roku_builder/test_files/navigator_intergration_test/images/rde_splash_hd.jpg +0 -0
  65. data/intergration/roku_builder/test_files/navigator_intergration_test/images/rde_splash_sd.jpg +0 -0
  66. data/intergration/roku_builder/test_files/navigator_intergration_test/images/rsgde_bg_hd.jpg +0 -0
  67. data/intergration/roku_builder/test_files/navigator_intergration_test/images/rsgde_mm_focus_hd.jpg +0 -0
  68. data/intergration/roku_builder/test_files/navigator_intergration_test/images/rsgde_splash_hd.jpg +0 -0
  69. data/intergration/roku_builder/test_files/navigator_intergration_test/manifest +21 -0
  70. data/intergration/roku_builder/test_files/navigator_intergration_test/source/main.brs +21 -0
  71. data/intergration/roku_builder/test_files/navigator_intergration_test/test.pkg +0 -0
  72. data/intergration/roku_builder/test_files/packager_intergration_test/components/rectanglescene.xml +29 -0
  73. data/intergration/roku_builder/test_files/packager_intergration_test/images/rde_mm_focus_hd.jpg +0 -0
  74. data/intergration/roku_builder/test_files/packager_intergration_test/images/rde_mm_focus_sd.jpg +0 -0
  75. data/intergration/roku_builder/test_files/packager_intergration_test/images/rde_splash_fhd.jpg +0 -0
  76. data/intergration/roku_builder/test_files/packager_intergration_test/images/rde_splash_hd.jpg +0 -0
  77. data/intergration/roku_builder/test_files/packager_intergration_test/images/rde_splash_sd.jpg +0 -0
  78. data/intergration/roku_builder/test_files/packager_intergration_test/images/rsgde_bg_hd.jpg +0 -0
  79. data/intergration/roku_builder/test_files/packager_intergration_test/images/rsgde_mm_focus_hd.jpg +0 -0
  80. data/intergration/roku_builder/test_files/packager_intergration_test/images/rsgde_splash_hd.jpg +0 -0
  81. data/intergration/roku_builder/test_files/packager_intergration_test/manifest +21 -0
  82. data/intergration/roku_builder/test_files/packager_intergration_test/source/main.brs +21 -0
  83. data/intergration/roku_builder/test_files/packager_intergration_test/test.pkg +0 -0
  84. data/intergration/roku_builder/test_files/profiler_intergration_test/components/rectanglescene.xml +29 -0
  85. data/intergration/roku_builder/test_files/profiler_intergration_test/images/rde_mm_focus_hd.jpg +0 -0
  86. data/intergration/roku_builder/test_files/profiler_intergration_test/images/rde_mm_focus_sd.jpg +0 -0
  87. data/intergration/roku_builder/test_files/profiler_intergration_test/images/rde_splash_fhd.jpg +0 -0
  88. data/intergration/roku_builder/test_files/profiler_intergration_test/images/rde_splash_hd.jpg +0 -0
  89. data/intergration/roku_builder/test_files/profiler_intergration_test/images/rde_splash_sd.jpg +0 -0
  90. data/intergration/roku_builder/test_files/profiler_intergration_test/images/rsgde_bg_hd.jpg +0 -0
  91. data/intergration/roku_builder/test_files/profiler_intergration_test/images/rsgde_mm_focus_hd.jpg +0 -0
  92. data/intergration/roku_builder/test_files/profiler_intergration_test/images/rsgde_splash_hd.jpg +0 -0
  93. data/intergration/roku_builder/test_files/profiler_intergration_test/manifest +21 -0
  94. data/intergration/roku_builder/test_files/profiler_intergration_test/source/main.brs +21 -0
  95. data/intergration/roku_builder/test_files/profiler_intergration_test/test.pkg +0 -0
  96. data/intergration/roku_builder/test_files/scripter_intergration_test/components/rectanglescene.xml +29 -0
  97. data/intergration/roku_builder/test_files/scripter_intergration_test/images/rde_mm_focus_hd.jpg +0 -0
  98. data/intergration/roku_builder/test_files/scripter_intergration_test/images/rde_mm_focus_sd.jpg +0 -0
  99. data/intergration/roku_builder/test_files/scripter_intergration_test/images/rde_splash_fhd.jpg +0 -0
  100. data/intergration/roku_builder/test_files/scripter_intergration_test/images/rde_splash_hd.jpg +0 -0
  101. data/intergration/roku_builder/test_files/scripter_intergration_test/images/rde_splash_sd.jpg +0 -0
  102. data/intergration/roku_builder/test_files/scripter_intergration_test/images/rsgde_bg_hd.jpg +0 -0
  103. data/intergration/roku_builder/test_files/scripter_intergration_test/images/rsgde_mm_focus_hd.jpg +0 -0
  104. data/intergration/roku_builder/test_files/scripter_intergration_test/images/rsgde_splash_hd.jpg +0 -0
  105. data/intergration/roku_builder/test_files/scripter_intergration_test/manifest +21 -0
  106. data/intergration/roku_builder/test_files/scripter_intergration_test/source/main.brs +21 -0
  107. data/intergration/roku_builder/test_files/scripter_intergration_test/test.pkg +0 -0
  108. data/intergration/roku_builder/test_files/tester_intergration_test/components/rectanglescene.xml +29 -0
  109. data/intergration/roku_builder/test_files/tester_intergration_test/images/rde_mm_focus_hd.jpg +0 -0
  110. data/intergration/roku_builder/test_files/tester_intergration_test/images/rde_mm_focus_sd.jpg +0 -0
  111. data/intergration/roku_builder/test_files/tester_intergration_test/images/rde_splash_fhd.jpg +0 -0
  112. data/intergration/roku_builder/test_files/tester_intergration_test/images/rde_splash_hd.jpg +0 -0
  113. data/intergration/roku_builder/test_files/tester_intergration_test/images/rde_splash_sd.jpg +0 -0
  114. data/intergration/roku_builder/test_files/tester_intergration_test/images/rsgde_bg_hd.jpg +0 -0
  115. data/intergration/roku_builder/test_files/tester_intergration_test/images/rsgde_mm_focus_hd.jpg +0 -0
  116. data/intergration/roku_builder/test_files/tester_intergration_test/images/rsgde_splash_hd.jpg +0 -0
  117. data/intergration/roku_builder/test_files/tester_intergration_test/manifest +21 -0
  118. data/intergration/roku_builder/test_files/tester_intergration_test/source/main.brs +21 -0
  119. data/intergration/roku_builder/test_files/tester_intergration_test/test.pkg +0 -0
  120. data/intergration/roku_builder/test_helper.rb +138 -0
  121. data/intergration/roku_builder/test_inspector.rb +35 -0
  122. data/intergration/roku_builder/test_linker.rb +32 -0
  123. data/intergration/roku_builder/test_loader.rb +38 -0
  124. data/intergration/roku_builder/test_monitor.rb +21 -0
  125. data/intergration/roku_builder/test_navigator.rb +34 -0
  126. data/intergration/roku_builder/test_packager.rb +41 -0
  127. data/intergration/roku_builder/test_profiler.rb +48 -0
  128. data/intergration/roku_builder/test_scripter.rb +38 -0
  129. data/intergration/roku_builder/test_tester.rb +21 -0
  130. data/lib/roku_builder.rb +143 -154
  131. data/lib/roku_builder/config.rb +17 -40
  132. data/lib/roku_builder/config_parser.rb +49 -200
  133. data/lib/roku_builder/config_validator.rb +1 -1
  134. data/lib/roku_builder/errors.rb +12 -0
  135. data/lib/roku_builder/git.rb +28 -0
  136. data/lib/roku_builder/hash.rb +8 -0
  137. data/lib/roku_builder/manifest.rb +121 -0
  138. data/lib/roku_builder/options.rb +68 -29
  139. data/lib/roku_builder/plugin.rb +30 -0
  140. data/lib/roku_builder/plugins/core.rb +117 -0
  141. data/lib/roku_builder/plugins/inspector.rb +104 -0
  142. data/lib/roku_builder/{linker.rb → plugins/linker.rb} +38 -12
  143. data/lib/roku_builder/plugins/loader.rb +152 -0
  144. data/lib/roku_builder/{monitor.rb → plugins/monitor.rb} +20 -9
  145. data/lib/roku_builder/{navigator.rb → plugins/navigator.rb} +136 -88
  146. data/lib/roku_builder/plugins/packager.rb +194 -0
  147. data/lib/roku_builder/plugins/profiler.rb +135 -0
  148. data/lib/roku_builder/plugins/scripter.rb +53 -0
  149. data/lib/roku_builder/{tester.rb → plugins/tester.rb} +28 -19
  150. data/lib/roku_builder/stager.rb +48 -12
  151. data/lib/roku_builder/string.rb +20 -0
  152. data/lib/roku_builder/util.rb +10 -34
  153. data/lib/roku_builder/version.rb +1 -1
  154. data/rakefile +5 -1
  155. data/roku_builder.gemspec +2 -0
  156. data/test/roku_builder/plugins/test_core.rb +112 -0
  157. data/test/roku_builder/plugins/test_inspector.rb +165 -0
  158. data/test/roku_builder/plugins/test_linker.rb +123 -0
  159. data/test/roku_builder/plugins/test_loader.rb +115 -0
  160. data/test/roku_builder/plugins/test_monitor.rb +141 -0
  161. data/test/roku_builder/plugins/test_navigator.rb +274 -0
  162. data/test/roku_builder/plugins/test_packager.rb +202 -0
  163. data/test/roku_builder/plugins/test_profiler.rb +127 -0
  164. data/test/roku_builder/plugins/test_scripter.rb +110 -0
  165. data/test/roku_builder/plugins/test_tester.rb +109 -0
  166. data/test/roku_builder/test_config.rb +51 -35
  167. data/test/roku_builder/test_config_parser.rb +76 -154
  168. data/test/roku_builder/test_config_validator.rb +18 -1
  169. data/test/roku_builder/test_files/{loader_test/manifest → config_parser_test/test.pkg} +0 -0
  170. data/test/roku_builder/test_files/config_test/config.json +3 -0
  171. data/test/roku_builder/test_files/controller_commands_test/manifest_template +7 -0
  172. data/test/roku_builder/test_files/core_test/manifest_template +7 -0
  173. data/test/roku_builder/test_files/core_test/test.pkg +0 -0
  174. data/test/roku_builder/test_files/inspector_test/manifest +6 -0
  175. data/test/roku_builder/test_files/inspector_test/test.pkg +0 -0
  176. data/test/roku_builder/test_files/linker_test/manifest +6 -0
  177. data/test/roku_builder/test_files/linker_test/test.pkg +0 -0
  178. data/test/roku_builder/test_files/loader_test/manifest_template +6 -0
  179. data/test/roku_builder/test_files/loader_test/test.pkg +0 -0
  180. data/test/roku_builder/test_files/loader_test/test.zip +0 -0
  181. data/test/roku_builder/test_files/manifest_test/manifest_comments +6 -0
  182. data/test/roku_builder/test_files/manifest_test/manifest_template +7 -0
  183. data/test/roku_builder/test_files/manifest_test/test.zip +0 -0
  184. data/test/roku_builder/test_files/packager_test/manifest +6 -0
  185. data/test/roku_builder/test_files/packager_test/scripter_test/manifest +6 -0
  186. data/test/roku_builder/test_files/packager_test/test.pkg +0 -0
  187. data/test/roku_builder/test_files/roku_builder_test/config.json +32 -0
  188. data/test/roku_builder/test_files/scripter_test/manifest +6 -0
  189. data/test/roku_builder/test_files/scripter_test/test.pkg +0 -0
  190. data/test/roku_builder/test_files/stager_test/test.pkg +0 -0
  191. data/test/roku_builder/test_files/tester_test/manifest +6 -0
  192. data/test/roku_builder/test_files/tester_test/test.pkg +0 -0
  193. data/test/roku_builder/test_helper.rb +44 -11
  194. data/test/roku_builder/test_logger.rb +1 -0
  195. data/test/roku_builder/test_manifest.rb +99 -0
  196. data/test/roku_builder/test_options.rb +106 -77
  197. data/test/roku_builder/test_options_plugins.rb +111 -0
  198. data/test/roku_builder/test_plugin.rb +48 -0
  199. data/test/roku_builder/test_roku_builder.rb +239 -0
  200. data/test/roku_builder/test_stager.rb +49 -101
  201. data/test/roku_builder/test_util.rb +19 -4
  202. metadata +241 -47
  203. data/lib/roku_builder/controller.rb +0 -98
  204. data/lib/roku_builder/controller_commands.rb +0 -224
  205. data/lib/roku_builder/error_handler.rb +0 -142
  206. data/lib/roku_builder/inspector.rb +0 -82
  207. data/lib/roku_builder/keyer.rb +0 -106
  208. data/lib/roku_builder/loader.rb +0 -131
  209. data/lib/roku_builder/manifest_manager.rb +0 -126
  210. data/lib/roku_builder/packager.rb +0 -43
  211. data/lib/roku_builder/profiler.rb +0 -96
  212. data/lib/roku_builder/scripter.rb +0 -39
  213. data/test/roku_builder/test_controller.rb +0 -70
  214. data/test/roku_builder/test_controller_commands.rb +0 -465
  215. data/test/roku_builder/test_error_handler.rb +0 -90
  216. data/test/roku_builder/test_inspector.rb +0 -298
  217. data/test/roku_builder/test_keyer.rb +0 -176
  218. data/test/roku_builder/test_linker.rb +0 -110
  219. data/test/roku_builder/test_loader.rb +0 -337
  220. data/test/roku_builder/test_manifest_manager.rb +0 -103
  221. data/test/roku_builder/test_monitor.rb +0 -137
  222. data/test/roku_builder/test_navigator.rb +0 -280
  223. data/test/roku_builder/test_packager.rb +0 -127
  224. data/test/roku_builder/test_profiler.rb +0 -35
  225. data/test/roku_builder/test_scripter.rb +0 -102
  226. data/test/roku_builder/test_tester.rb +0 -130
@@ -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
@@ -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