roku_builder 3.3.3 → 3.3.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rubocop.yml +1158 -0
- data/.travis.yml +3 -0
- data/Gemfile.lock +19 -14
- data/README.md +5 -0
- data/bin/roku +32 -37
- data/config.json.example +2 -2
- data/lib/roku_builder/config_manager.rb +83 -118
- data/lib/roku_builder/config_parser.rb +192 -0
- data/lib/roku_builder/config_validator.rb +125 -0
- data/lib/roku_builder/controller.rb +97 -484
- data/lib/roku_builder/controller_commands.rb +112 -0
- data/lib/roku_builder/error_handler.rb +116 -0
- data/lib/roku_builder/inspector.rb +5 -18
- data/lib/roku_builder/keyer.rb +3 -11
- data/lib/roku_builder/linker.rb +3 -15
- data/lib/roku_builder/loader.rb +52 -89
- data/lib/roku_builder/manifest_manager.rb +2 -3
- data/lib/roku_builder/monitor.rb +15 -12
- data/lib/roku_builder/navigator.rb +2 -10
- data/lib/roku_builder/packager.rb +1 -7
- data/lib/roku_builder/tester.rb +1 -0
- data/lib/roku_builder/util.rb +39 -0
- data/lib/roku_builder/version.rb +1 -1
- data/lib/roku_builder.rb +96 -1
- data/roku_builder.gemspec +5 -4
- data/tests/roku_builder/config_manager_test.rb +80 -241
- data/tests/roku_builder/{controller_config_test.rb → config_parser_test.rb} +5 -5
- data/tests/roku_builder/config_validator_test.rb +158 -0
- data/tests/roku_builder/controller_commands_test.rb +304 -0
- data/tests/roku_builder/controller_test.rb +61 -620
- data/tests/roku_builder/error_handler_test.rb +76 -0
- data/tests/roku_builder/inspector_test.rb +3 -0
- data/tests/roku_builder/keyer_test.rb +3 -2
- data/tests/roku_builder/linker_test.rb +2 -1
- data/tests/roku_builder/loader_test.rb +2 -0
- data/tests/roku_builder/manifest_manager_test.rb +3 -6
- data/tests/roku_builder/monitor_test.rb +5 -13
- data/tests/roku_builder/navigator_test.rb +2 -0
- data/tests/roku_builder/test_helper.rb +38 -0
- metadata +34 -11
@@ -0,0 +1,112 @@
|
|
1
|
+
module RokuBuilder
|
2
|
+
|
3
|
+
# Commands that the controller uses to interface with the rest of the gem.
|
4
|
+
class ControllerCommands
|
5
|
+
|
6
|
+
# Provides a hash of all of the options needed to run simple commands via
|
7
|
+
# the simple_command method
|
8
|
+
# @return [Hash] options to run simple commands
|
9
|
+
def self.simple_commands
|
10
|
+
{
|
11
|
+
sideload: { klass: Loader, method: :sideload, config_key: :sideload_config,
|
12
|
+
failure: FAILED_SIDELOAD },
|
13
|
+
deeplink: { klass: Linker, method: :link, config_key: :deeplink_config,
|
14
|
+
failure: FAILED_DEEPLINKING },
|
15
|
+
delete: { klass: Loader, method: :unload },
|
16
|
+
monitor: { klass: Monitor, method: :monitor,
|
17
|
+
config_key: :monitor_config },
|
18
|
+
navigate: { klass: Navigator, method: :nav, config_key: :navigate_config,
|
19
|
+
failure: FAILED_NAVIGATING },
|
20
|
+
screen: { klass: Navigator, method: :screen, config_key: :screen_config,
|
21
|
+
failure: FAILED_NAVIGATING },
|
22
|
+
screens: { klass: Navigator, method: :screens },
|
23
|
+
text: { klass: Navigator, method: :type, config_key: :text_config },
|
24
|
+
test: { klass: Tester, method: :run_tests, config_key: :test_config },
|
25
|
+
screencapture: { klass: Inspector, method: :screencapture, config_key: :screencapture_config,
|
26
|
+
failure: FAILED_SCREENCAPTURE }
|
27
|
+
}
|
28
|
+
end
|
29
|
+
# Validate Config
|
30
|
+
# @return [Integer] Success or Failure Code
|
31
|
+
def self.validate()
|
32
|
+
SUCCESS
|
33
|
+
end
|
34
|
+
# Run Package
|
35
|
+
# @param options [Hash] user options
|
36
|
+
# @param configs [Hash] parsed configs
|
37
|
+
# @param logger [Logger] system logger
|
38
|
+
# @return [Integer] Success or Failure Code
|
39
|
+
def self.package(options:, configs:, logger:)
|
40
|
+
keyer = Keyer.new(**configs[:device_config])
|
41
|
+
loader = Loader.new(**configs[:device_config])
|
42
|
+
packager = Packager.new(**configs[:device_config])
|
43
|
+
inspector = Inspector.new(**configs[:device_config])
|
44
|
+
logger.warn "Packaging working directory" if options[:working]
|
45
|
+
# Sideload #
|
46
|
+
build_version = loader.sideload(**configs[:sideload_config])
|
47
|
+
return FAILED_SIGNING unless build_version
|
48
|
+
# Key #
|
49
|
+
success = keyer.rekey(**configs[:key])
|
50
|
+
logger.info "Key did not change" unless success
|
51
|
+
# Package #
|
52
|
+
options[:build_version] = build_version
|
53
|
+
configs = ConfigManager.update_configs(configs: configs, options: options)
|
54
|
+
success = packager.package(**configs[:package_config])
|
55
|
+
logger.info "Signing Successful: #{configs[:package_config][:out_file]}" if success
|
56
|
+
return FAILED_SIGNING unless success
|
57
|
+
# Inspect #
|
58
|
+
if options[:inspect]
|
59
|
+
info = inspector.inspect(configs[:inspect_config])
|
60
|
+
logger.unknown "App Name: #{info[:app_name]}"
|
61
|
+
logger.unknown "Dev ID: #{info[:dev_id]}"
|
62
|
+
logger.unknown "Creation Date: #{info[:creation_date]}"
|
63
|
+
logger.unknown "dev.zip: #{info[:dev_zip]}"
|
64
|
+
end
|
65
|
+
SUCCESS
|
66
|
+
end
|
67
|
+
# Run Build
|
68
|
+
# @param options [Hash] user options
|
69
|
+
# @param configs [Hash] parsed configs
|
70
|
+
# @param logger [Logger] system logger
|
71
|
+
# @return [Integer] Success or Failure Code
|
72
|
+
def self.build(options:, configs:, logger:)
|
73
|
+
### Build ###
|
74
|
+
loader = Loader.new(**configs[:device_config])
|
75
|
+
build_version = ManifestManager.build_version(**configs[:manifest_config])
|
76
|
+
options[:build_version] = build_version
|
77
|
+
configs = ConfigManager.update_configs(configs: configs, options: options)
|
78
|
+
outfile = loader.build(**configs[:build_config])
|
79
|
+
logger.info "Build: #{outfile}"
|
80
|
+
SUCCESS
|
81
|
+
end
|
82
|
+
# Run update
|
83
|
+
# @param configs [Hash] parsed configs
|
84
|
+
# @param logger [Logger] system logger
|
85
|
+
# @return [Integer] Success or Failure Code
|
86
|
+
def self.update(configs:, logger:)
|
87
|
+
### Update ###
|
88
|
+
old_version = ManifestManager.build_version(**configs[:manifest_config])
|
89
|
+
new_version = ManifestManager.update_build(**configs[:manifest_config])
|
90
|
+
logger.info "Update build version from:\n#{old_version}\nto:\n#{new_version}"
|
91
|
+
SUCCESS
|
92
|
+
end
|
93
|
+
|
94
|
+
# Run a simple command
|
95
|
+
# @param klass [Class] class of object to create
|
96
|
+
# @param method [Symbol] methog to run on klass
|
97
|
+
# @param config_key [Symbol] config to send from configs if not nil
|
98
|
+
# @param configs [Hash] parsed roku config
|
99
|
+
# @param failure [Integer] failure code to return on failure if not nil
|
100
|
+
# @return [Integer] Success of failure code
|
101
|
+
def self.simple_command(klass:, method:, config_key: nil, configs:, failure: nil)
|
102
|
+
instance = klass.new(**configs[:device_config])
|
103
|
+
if config_key
|
104
|
+
success = instance.send(method, configs[config_key])
|
105
|
+
else
|
106
|
+
success = instance.send(method)
|
107
|
+
end
|
108
|
+
return failure unless failure.nil? or success
|
109
|
+
SUCCESS
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
module RokuBuilder
|
2
|
+
|
3
|
+
# Contains methods to handle errors from different sources.
|
4
|
+
class ErrorHandler
|
5
|
+
# Handle codes returned from validating options
|
6
|
+
# @param options_code [Integer] the error code returned by validate_options
|
7
|
+
# @param logger [Logger] system logger
|
8
|
+
def self.handle_options_codes(options_code:, logger:)
|
9
|
+
case options_code
|
10
|
+
when EXTRA_COMMANDS
|
11
|
+
logger.fatal "Only one command is allowed"
|
12
|
+
abort
|
13
|
+
when NO_COMMANDS
|
14
|
+
logger.fatal "At least one command is required"
|
15
|
+
abort
|
16
|
+
when EXTRA_SOURCES
|
17
|
+
logger.fatal "Only use one of --ref, --working, --current or --stage"
|
18
|
+
abort
|
19
|
+
when NO_SOURCE
|
20
|
+
logger.fatal "Must use at least one of --ref, --working, --current or --stage"
|
21
|
+
abort
|
22
|
+
when BAD_CURRENT
|
23
|
+
logger.fatal "Can only sideload or build 'current' directory"
|
24
|
+
abort
|
25
|
+
when BAD_DEEPLINK
|
26
|
+
logger.fatal "Must supply deeplinking options when deeplinking"
|
27
|
+
abort
|
28
|
+
when BAD_IN_FILE
|
29
|
+
logger.fatal "Can only supply in file for building"
|
30
|
+
abort
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Handle codes returned from configuring
|
35
|
+
# @param configure_code [Integer] the error code returned by configure
|
36
|
+
# @param logger [Logger] system logger
|
37
|
+
def self.handle_configure_codes(configure_code:, logger:)
|
38
|
+
case configure_code
|
39
|
+
when CONFIG_OVERWRITE
|
40
|
+
logger.fatal 'Config already exists. To create default please remove config first.'
|
41
|
+
abort
|
42
|
+
when SUCCESS
|
43
|
+
logger.info 'Configure successful'
|
44
|
+
abort
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Handle codes returned from load_config
|
49
|
+
# @param options [Hash] the options hash
|
50
|
+
# @param load_code [Integer] the error code returned by configure
|
51
|
+
# @param logger [Logger] system logger
|
52
|
+
def self.handle_load_codes(options:, load_code:, logger:)
|
53
|
+
case load_code
|
54
|
+
when DEPRICATED_CONFIG
|
55
|
+
logger.warn 'Depricated config. See Above'
|
56
|
+
when MISSING_CONFIG
|
57
|
+
logger.fatal "Missing config file: #{options[:config]}"
|
58
|
+
abort
|
59
|
+
when INVALID_CONFIG
|
60
|
+
logger.fatal 'Invalid config. See Above'
|
61
|
+
abort
|
62
|
+
when MISSING_MANIFEST
|
63
|
+
logger.fatal 'Manifest file missing'
|
64
|
+
abort
|
65
|
+
when UNKNOWN_DEVICE
|
66
|
+
logger.fatal "Unkown device id"
|
67
|
+
abort
|
68
|
+
when UNKNOWN_PROJECT
|
69
|
+
logger.fatal "Unknown project id"
|
70
|
+
abort
|
71
|
+
when UNKNOWN_STAGE
|
72
|
+
logger.fatal "Unknown stage"
|
73
|
+
abort
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# Handle codes returned from checking devices
|
78
|
+
# @param device_code [Integer] the error code returned by check_devices
|
79
|
+
# @param logger [Logger] system logger
|
80
|
+
def self.handle_device_codes(device_code:, logger:)
|
81
|
+
case device_code
|
82
|
+
when CHANGED_DEVICE
|
83
|
+
logger.info "The default device was not online so a secondary device is being used"
|
84
|
+
when BAD_DEVICE
|
85
|
+
logger.fatal "The selected device was not online"
|
86
|
+
abort
|
87
|
+
when NO_DEVICES
|
88
|
+
logger.fatal "No configured devices were found"
|
89
|
+
abort
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# Handle codes returned from handeling commands devices
|
94
|
+
# @param command_code [Integer] the error code returned by handle_options
|
95
|
+
# @param logger [Logger] system logger
|
96
|
+
def self.handle_command_codes(command_code:, logger:)
|
97
|
+
case command_code
|
98
|
+
when FAILED_SIDELOAD
|
99
|
+
logger.fatal "Failed Sideloading App"
|
100
|
+
abort
|
101
|
+
when FAILED_SIGNING
|
102
|
+
logger.fatal "Failed Signing App"
|
103
|
+
abort
|
104
|
+
when FAILED_DEEPLINKING
|
105
|
+
logger.fatal "Failed Deeplinking To App"
|
106
|
+
abort
|
107
|
+
when FAILED_NAVIGATING
|
108
|
+
logger.fatal "Command not sent"
|
109
|
+
abort
|
110
|
+
when FAILED_SCREENCAPTURE
|
111
|
+
logger.fatal "Failed to Capture Screen"
|
112
|
+
abort
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -15,12 +15,7 @@ module RokuBuilder
|
|
15
15
|
|
16
16
|
# upload new key with password
|
17
17
|
path = "/plugin_inspect"
|
18
|
-
conn =
|
19
|
-
f.request :digest, @dev_username, @dev_password
|
20
|
-
f.request :multipart
|
21
|
-
f.request :url_encoded
|
22
|
-
f.adapter Faraday.default_adapter
|
23
|
-
end
|
18
|
+
conn = multipart_connection
|
24
19
|
payload = {
|
25
20
|
mysubmit: "Inspect",
|
26
21
|
passwd: password,
|
@@ -35,12 +30,12 @@ module RokuBuilder
|
|
35
30
|
if app_name
|
36
31
|
app_name = app_name[1]
|
37
32
|
dev_id = /Dev ID:\s*<\/td>\s*<td>\s*<font[^>]*>([^<]*)<\/font>\s*<\/td>/.match(response.body)[1]
|
38
|
-
creation_date = /new Date\(([^)]*)\)/.match(response.body.
|
33
|
+
creation_date = /new Date\(([^)]*)\)/.match(response.body.delete("\n"))[1]
|
39
34
|
dev_zip = /dev.zip:\s*<\/td>\s*<td>\s*<font[^>]*>([^<]*)<\/font>\s*<\/td>/.match(response.body)[1]
|
40
35
|
else
|
41
36
|
app_name = /App Name:[^<]*<div[^>]*>([^<]*)<\/div>/.match(response.body)[1]
|
42
37
|
dev_id = /Dev ID:[^<]*<div[^>]*><font[^>]*>([^<]*)<\/font><\/div>/.match(response.body)[1]
|
43
|
-
creation_date = /new Date\(([^\/]*)\)/.match(response.body.
|
38
|
+
creation_date = /new Date\(([^\/]*)\)/.match(response.body.delete("\n"))[1]
|
44
39
|
dev_zip = /dev.zip:[^<]*<div[^>]*><font[^>]*>([^<]*)<\/font><\/div>/.match(response.body)[1]
|
45
40
|
end
|
46
41
|
|
@@ -52,12 +47,7 @@ module RokuBuilder
|
|
52
47
|
# @return [Boolean] Success
|
53
48
|
def screencapture(out_folder:, out_file: nil)
|
54
49
|
path = "/plugin_inspect"
|
55
|
-
conn =
|
56
|
-
f.request :digest, @dev_username, @dev_password
|
57
|
-
f.request :multipart
|
58
|
-
f.request :url_encoded
|
59
|
-
f.adapter Faraday.default_adapter
|
60
|
-
end
|
50
|
+
conn = multipart_connection
|
61
51
|
payload = {
|
62
52
|
mysubmit: "Screenshot",
|
63
53
|
passwd: @dev_password,
|
@@ -73,10 +63,7 @@ module RokuBuilder
|
|
73
63
|
out_file = "dev_#{out_file[1]}.jpg" if out_file
|
74
64
|
end
|
75
65
|
|
76
|
-
conn =
|
77
|
-
f.request :digest, @dev_username, @dev_password
|
78
|
-
f.adapter Faraday.default_adapter
|
79
|
-
end
|
66
|
+
conn = simple_connection
|
80
67
|
|
81
68
|
response = conn.get path
|
82
69
|
|
data/lib/roku_builder/keyer.rb
CHANGED
@@ -12,18 +12,13 @@ module RokuBuilder
|
|
12
12
|
|
13
13
|
# upload new key with password
|
14
14
|
path = "/plugin_inspect"
|
15
|
-
conn =
|
16
|
-
f.request :digest, @dev_username, @dev_password
|
17
|
-
f.request :multipart
|
18
|
-
f.request :url_encoded
|
19
|
-
f.adapter Faraday.default_adapter
|
20
|
-
end
|
15
|
+
conn = multipart_connection
|
21
16
|
payload = {
|
22
17
|
mysubmit: "Rekey",
|
23
18
|
passwd: password,
|
24
19
|
archive: Faraday::UploadIO.new(keyed_pkg, 'application/octet-stream')
|
25
20
|
}
|
26
|
-
|
21
|
+
conn.post path, payload
|
27
22
|
|
28
23
|
# check key
|
29
24
|
newId = dev_id
|
@@ -34,10 +29,7 @@ module RokuBuilder
|
|
34
29
|
# @return [String] The current dev id
|
35
30
|
def dev_id
|
36
31
|
path = "/plugin_package"
|
37
|
-
conn =
|
38
|
-
f.request :digest, @dev_username, @dev_password
|
39
|
-
f.adapter Faraday.default_adapter
|
40
|
-
end
|
32
|
+
conn = simple_connection
|
41
33
|
response = conn.get path
|
42
34
|
|
43
35
|
dev_id = /Your Dev ID:\s*<font[^>]*>([^<]*)<\/font>/.match(response.body)
|
data/lib/roku_builder/linker.rb
CHANGED
@@ -8,27 +8,15 @@ module RokuBuilder
|
|
8
8
|
# @note Any options will be accepted and sent to the app
|
9
9
|
def link(options:)
|
10
10
|
path = "/launch/dev"
|
11
|
-
payload = {}
|
12
11
|
return false unless options
|
13
|
-
|
14
|
-
opts.each do |opt|
|
15
|
-
opt = opt.split(":")
|
16
|
-
key = opt.shift.to_sym
|
17
|
-
value = opt.join(":")
|
18
|
-
payload[key] = value
|
19
|
-
end
|
12
|
+
payload = Util.options_parse(options: options)
|
20
13
|
|
21
14
|
unless payload.keys.count > 0
|
22
15
|
return false
|
23
16
|
end
|
24
17
|
|
25
18
|
path = "#{path}?#{parameterize(payload)}"
|
26
|
-
conn =
|
27
|
-
f.request :digest, @dev_username, @dev_password
|
28
|
-
f.request :multipart
|
29
|
-
f.request :url_encoded
|
30
|
-
f.adapter Faraday.default_adapter
|
31
|
-
end
|
19
|
+
conn = multipart_connection(port: 8060)
|
32
20
|
|
33
21
|
response = conn.post path
|
34
22
|
return response.success?
|
@@ -40,7 +28,7 @@ module RokuBuilder
|
|
40
28
|
# @param params [Hash] Parameters to be sent
|
41
29
|
# @return [String] Parameters as a string, URI escaped
|
42
30
|
def parameterize(params)
|
43
|
-
|
31
|
+
params.collect{|k,v| "#{k}=#{CGI.escape(v)}"}.join('&')
|
44
32
|
end
|
45
33
|
end
|
46
34
|
end
|
data/lib/roku_builder/loader.rb
CHANGED
@@ -7,75 +7,39 @@ module RokuBuilder
|
|
7
7
|
# @param root_dir [String] Path to the root directory of the roku app
|
8
8
|
# @param branch [String] Branch of the git repository to sideload. Pass nil to use working directory. Default: nil
|
9
9
|
# @param update_manifest [Boolean] Flag to update the manifest file before sideloading. Default: false
|
10
|
-
# @param fetch [Boolean] Flag to fetch all remotes before sideloading. Default: false
|
11
10
|
# @param folders [Array<String>] Array of folders to be sideloaded. Pass nil to send all folders. Default: nil
|
12
11
|
# @param files [Array<String>] Array of files to be sideloaded. Pass nil to send all files. Default: nil
|
13
|
-
# @param infile [String]
|
14
12
|
# @return [String] Build version on success, nil otherwise
|
15
|
-
def sideload(root_dir:, branch: nil, update_manifest: false,
|
13
|
+
def sideload(root_dir:, branch: nil, update_manifest: false, folders: nil, files: nil)
|
16
14
|
@root_dir = root_dir
|
17
15
|
result = nil
|
18
|
-
stash = nil
|
19
|
-
if branch
|
20
|
-
git = Git.open(@root_dir)
|
21
|
-
if fetch
|
22
|
-
for remote in git.remotes
|
23
|
-
git.fetch(remote)
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
current_dir = Dir.pwd
|
28
16
|
begin
|
29
|
-
|
30
|
-
Dir.chdir(@root_dir)
|
31
|
-
current_branch = git.current_branch
|
32
|
-
stash = git.branch.stashes.save("roku-builder-temp-stash")
|
33
|
-
git.checkout(branch)
|
34
|
-
end
|
35
|
-
|
17
|
+
git_switch_to(branch: branch)
|
36
18
|
# Update manifest
|
37
19
|
build_version = ""
|
38
20
|
if update_manifest
|
39
|
-
build_version = ManifestManager.update_build(root_dir: root_dir
|
21
|
+
build_version = ManifestManager.update_build(root_dir: root_dir)
|
40
22
|
else
|
41
|
-
build_version = ManifestManager.build_version(root_dir: root_dir
|
23
|
+
build_version = ManifestManager.build_version(root_dir: root_dir)
|
42
24
|
end
|
43
|
-
|
44
25
|
outfile = build(root_dir: root_dir, branch: branch, build_version: build_version, folders: folders, files: files)
|
45
|
-
|
46
26
|
path = "/plugin_install"
|
47
|
-
|
48
27
|
# Connect to roku and upload file
|
49
|
-
conn =
|
50
|
-
f.request :digest, @dev_username, @dev_password
|
51
|
-
f.request :multipart
|
52
|
-
f.request :url_encoded
|
53
|
-
f.adapter Faraday.default_adapter
|
54
|
-
end
|
28
|
+
conn = multipart_connection
|
55
29
|
payload = {
|
56
30
|
mysubmit: "Replace",
|
57
31
|
archive: Faraday::UploadIO.new(outfile, 'application/zip')
|
58
32
|
}
|
59
33
|
response = conn.post path, payload
|
60
|
-
|
61
34
|
# Cleanup
|
62
35
|
File.delete(outfile)
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
end
|
68
|
-
|
69
|
-
if response.status == 200 and response.body =~ /Install Success/
|
70
|
-
result = build_version
|
71
|
-
end
|
72
|
-
|
73
|
-
rescue Git::GitExecuteError => e
|
74
|
-
@logger.error "Branch or ref does not exist"
|
75
|
-
@logger.error e.message
|
76
|
-
@logger.error e.backtrace
|
36
|
+
result = build_version if response.status==200 and response.body=~/Install Success/
|
37
|
+
git_switch_from(branch: branch)
|
38
|
+
rescue Git::GitExecuteError
|
39
|
+
git_rescue
|
77
40
|
ensure
|
78
|
-
|
41
|
+
@current_dir ||= Dir.pwd
|
42
|
+
Dir.chdir(@current_dir) unless @current_dir == Dir.pwd
|
79
43
|
end
|
80
44
|
result
|
81
45
|
end
|
@@ -86,31 +50,13 @@ module RokuBuilder
|
|
86
50
|
# @param branch [String] Branch of the git repository to sideload. Pass nil to use working directory. Default: nil
|
87
51
|
# @param build_version [String] Version to assigne to the build. If nil will pull the build version form the manifest. Default: nil
|
88
52
|
# @param outfile [String] Path for the output file. If nil will create a file in /tmp. Default: nil
|
89
|
-
# @param fetch [Boolean] Flag to fetch all remotes before sideloading. Default: false
|
90
53
|
# @param folders [Array<String>] Array of folders to be sideloaded. Pass nil to send all folders. Default: nil
|
91
54
|
# @param files [Array<String>] Array of files to be sideloaded. Pass nil to send all files. Default: nil
|
92
55
|
# @return [String] Path of the build
|
93
|
-
def build(root_dir:, branch: nil, build_version: nil, outfile: nil,
|
56
|
+
def build(root_dir:, branch: nil, build_version: nil, outfile: nil, folders: nil, files: nil)
|
94
57
|
@root_dir = root_dir
|
95
|
-
result = nil
|
96
|
-
stash = nil
|
97
|
-
if branch
|
98
|
-
git = Git.open(@root_dir)
|
99
|
-
if fetch
|
100
|
-
for remote in git.remotes
|
101
|
-
git.fetch(remote)
|
102
|
-
end
|
103
|
-
end
|
104
|
-
end
|
105
|
-
current_dir = Dir.pwd
|
106
58
|
begin
|
107
|
-
|
108
|
-
Dir.chdir(@root_dir)
|
109
|
-
current_branch = git.current_branch
|
110
|
-
stash = git.branch.stashes.save("roku-builder-temp-stash")
|
111
|
-
git.checkout(branch)
|
112
|
-
end
|
113
|
-
|
59
|
+
git_switch_to(branch: branch)
|
114
60
|
build_version = ManifestManager.build_version(root_dir: root_dir, logger: @logger) unless build_version
|
115
61
|
unless folders
|
116
62
|
folders = Dir.entries(root_dir).select {|entry| File.directory? File.join(root_dir, entry) and !(entry =='.' || entry == '..') }
|
@@ -119,10 +65,8 @@ module RokuBuilder
|
|
119
65
|
files = Dir.entries(root_dir).select {|entry| File.file? File.join(root_dir, entry)}
|
120
66
|
end
|
121
67
|
outfile = "/tmp/build_#{build_version}.zip" unless outfile
|
122
|
-
|
123
|
-
File.delete(outfile) if File.exists?(outfile)
|
68
|
+
File.delete(outfile) if File.exist?(outfile)
|
124
69
|
io = Zip::File.open(outfile, Zip::File::CREATE)
|
125
|
-
|
126
70
|
# Add folders to zip
|
127
71
|
folders.each do |folder|
|
128
72
|
base_folder = File.join(@root_dir, folder)
|
@@ -131,22 +75,15 @@ module RokuBuilder
|
|
131
75
|
entries.delete("..")
|
132
76
|
writeEntries(@root_dir, entries, folder, io)
|
133
77
|
end
|
134
|
-
|
135
78
|
# Add file to zip
|
136
79
|
writeEntries(@root_dir, files, "", io)
|
137
|
-
|
138
80
|
io.close()
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
git.branch.stashes.apply if stash
|
143
|
-
end
|
144
|
-
rescue Git::GitExecuteError => e
|
145
|
-
@logger.error "Branch or ref does not exist"
|
146
|
-
@logger.error e.message
|
147
|
-
@logger.error e.backtrace
|
81
|
+
git_switch_from(branch: branch)
|
82
|
+
rescue Git::GitExecuteError
|
83
|
+
git_rescue
|
148
84
|
ensure
|
149
|
-
|
85
|
+
@current_dir ||= Dir.pwd
|
86
|
+
Dir.chdir(@current_dir) unless @current_dir == Dir.pwd
|
150
87
|
end
|
151
88
|
outfile
|
152
89
|
end
|
@@ -156,13 +93,7 @@ module RokuBuilder
|
|
156
93
|
path = "/plugin_install"
|
157
94
|
|
158
95
|
# Connect to roku and upload file
|
159
|
-
conn =
|
160
|
-
f.headers['Content-Type'] = Faraday::Request::Multipart.mime_type
|
161
|
-
f.request :digest, @dev_username, @dev_password
|
162
|
-
f.request :multipart
|
163
|
-
f.request :url_encoded
|
164
|
-
f.adapter Faraday.default_adapter
|
165
|
-
end
|
96
|
+
conn = multipart_connection
|
166
97
|
payload = {
|
167
98
|
mysubmit: "Delete",
|
168
99
|
archive: ""
|
@@ -194,5 +125,37 @@ module RokuBuilder
|
|
194
125
|
end
|
195
126
|
}
|
196
127
|
end
|
128
|
+
|
129
|
+
# Switch to the correct branch
|
130
|
+
def git_switch_to(branch:)
|
131
|
+
if branch
|
132
|
+
@current_dir = Dir.pwd
|
133
|
+
@git ||= Git.open(@root_dir)
|
134
|
+
if branch != @git.current_branch
|
135
|
+
Dir.chdir(@root_dir)
|
136
|
+
@current_branch = @git.current_branch
|
137
|
+
@stash = @git.branch.stashes.save("roku-builder-temp-stash")
|
138
|
+
@git.checkout(branch)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
# Switch back to the previous branch
|
144
|
+
def git_switch_from(branch:)
|
145
|
+
if branch
|
146
|
+
@git ||= Git.open(@root_dir)
|
147
|
+
if @git and @current_branch
|
148
|
+
@git.checkout(@current_branch)
|
149
|
+
@git.branch.stashes.apply if @stash
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
# Called if resuce from git exception
|
155
|
+
def git_rescue
|
156
|
+
@logger.error "Branch or ref does not exist"
|
157
|
+
@logger.error e.message
|
158
|
+
@logger.error e.backtrace
|
159
|
+
end
|
197
160
|
end
|
198
161
|
end
|
@@ -6,7 +6,7 @@ module RokuBuilder
|
|
6
6
|
# Updates the build version in the manifest file
|
7
7
|
# @param root_dir [String] Path to the root directory for the app
|
8
8
|
# @return [String] Build version on success, empty string otherwise
|
9
|
-
def self.update_build(root_dir
|
9
|
+
def self.update_build(root_dir:)
|
10
10
|
|
11
11
|
build_version = ""
|
12
12
|
|
@@ -19,7 +19,6 @@ module RokuBuilder
|
|
19
19
|
|
20
20
|
#Update build version.
|
21
21
|
build_version = line.split(".")
|
22
|
-
iteration = 0
|
23
22
|
if 2 == build_version.length
|
24
23
|
iteration = build_version[1].to_i + 1
|
25
24
|
build_version[0] = Time.now.strftime("%m%d%y")
|
@@ -47,7 +46,7 @@ module RokuBuilder
|
|
47
46
|
# Retrive the build version from the manifest file
|
48
47
|
# @param root_dir [String] Path to the root directory for the app
|
49
48
|
# @return [String] Build version on success, empty string otherwise
|
50
|
-
def self.build_version(root_dir
|
49
|
+
def self.build_version(root_dir:)
|
51
50
|
path = File.join(root_dir, 'manifest')
|
52
51
|
build_version = ""
|
53
52
|
File.open(path, 'r') do |file|
|
data/lib/roku_builder/monitor.rb
CHANGED
@@ -17,7 +17,6 @@ module RokuBuilder
|
|
17
17
|
|
18
18
|
# Monitor a development log on the Roku device
|
19
19
|
# @param type [Symbol] The log type to monitor
|
20
|
-
# @param verbose [Boolean] Print status messages.
|
21
20
|
def monitor(type:)
|
22
21
|
telnet_config = {
|
23
22
|
'Host' => @roku_ip_address,
|
@@ -28,26 +27,30 @@ module RokuBuilder
|
|
28
27
|
'Timeout' => false
|
29
28
|
}
|
30
29
|
|
31
|
-
thread = Thread.new(telnet_config, waitfor_config) {|
|
32
|
-
@logger.info "Monitoring #{type} console(#{
|
33
|
-
connection = Net::Telnet.new(
|
30
|
+
thread = Thread.new(telnet_config, waitfor_config) {|telnet,waitfor|
|
31
|
+
@logger.info "Monitoring #{type} console(#{telnet['Port']}) on #{telnet['Host'] }"
|
32
|
+
connection = Net::Telnet.new(telnet)
|
34
33
|
Thread.current[:connection] = connection
|
35
34
|
all_text = ""
|
36
35
|
while true
|
37
|
-
connection.waitfor(
|
36
|
+
connection.waitfor(waitfor) do |txt|
|
38
37
|
all_text = manage_text(all_text: all_text, txt: txt)
|
39
38
|
end
|
40
39
|
end
|
41
40
|
}
|
42
41
|
running = true
|
43
42
|
while running
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
43
|
+
begin
|
44
|
+
@logger.info "Q to exit"
|
45
|
+
command = gets.chomp
|
46
|
+
if command == "q"
|
47
|
+
thread.exit
|
48
|
+
running = false
|
49
|
+
else
|
50
|
+
thread[:connection].puts(command)
|
51
|
+
end
|
52
|
+
rescue SystemExit, Interrupt
|
53
|
+
thread[:connection].puts("\C-c")
|
51
54
|
end
|
52
55
|
end
|
53
56
|
end
|
@@ -38,11 +38,7 @@ module RokuBuilder
|
|
38
38
|
# @return [Boolean] Success
|
39
39
|
def nav(command:)
|
40
40
|
if @commands.has_key?(command)
|
41
|
-
conn =
|
42
|
-
f.request :multipart
|
43
|
-
f.request :url_encoded
|
44
|
-
f.adapter Faraday.default_adapter
|
45
|
-
end
|
41
|
+
conn = multipart_connection(port: 8060)
|
46
42
|
|
47
43
|
path = "/keypress/#{@commands[command]}"
|
48
44
|
response = conn.post path
|
@@ -56,11 +52,7 @@ module RokuBuilder
|
|
56
52
|
# @param text [String] The text to type on the device
|
57
53
|
# @return [Boolean] Success
|
58
54
|
def type(text:)
|
59
|
-
conn =
|
60
|
-
f.request :multipart
|
61
|
-
f.request :url_encoded
|
62
|
-
f.adapter Faraday.default_adapter
|
63
|
-
end
|
55
|
+
conn = multipart_connection(port: 8060)
|
64
56
|
text.split(//).each do |c|
|
65
57
|
path = "/keypress/LIT_#{CGI::escape(c)}"
|
66
58
|
response = conn.post path
|
@@ -11,13 +11,7 @@ module RokuBuilder
|
|
11
11
|
def package(app_name_version:, out_file:, password:)
|
12
12
|
# Sign package
|
13
13
|
path = "/plugin_package"
|
14
|
-
conn =
|
15
|
-
f.headers['Content-Type'] = Faraday::Request::Multipart.mime_type
|
16
|
-
f.request :digest, @dev_username, @dev_password
|
17
|
-
f.request :multipart
|
18
|
-
f.request :url_encoded
|
19
|
-
f.adapter Faraday.default_adapter
|
20
|
-
end
|
14
|
+
conn = multipart_connection
|
21
15
|
payload = {
|
22
16
|
mysubmit: "Package",
|
23
17
|
app_name: app_name_version,
|