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
data/.travis.yml
ADDED
data/Gemfile.lock
CHANGED
@@ -1,23 +1,24 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
roku_builder (3.3.
|
4
|
+
roku_builder (3.3.4)
|
5
5
|
faraday (~> 0.9)
|
6
6
|
faraday-digestauth (~> 0.2)
|
7
|
-
git (~> 1.
|
7
|
+
git (~> 1.3)
|
8
8
|
net-ping (~> 1.7)
|
9
|
-
rubyzip (~> 1.
|
9
|
+
rubyzip (~> 1.2)
|
10
10
|
|
11
11
|
GEM
|
12
12
|
remote: https://rubygems.org/
|
13
13
|
specs:
|
14
|
-
byebug (
|
15
|
-
columnize (~> 0.8)
|
16
|
-
debugger-linecache (~> 1.2)
|
17
|
-
slop (~> 3.6)
|
14
|
+
byebug (8.2.2)
|
18
15
|
coderay (1.1.0)
|
19
|
-
|
20
|
-
|
16
|
+
coveralls (0.8.13)
|
17
|
+
json (~> 1.8)
|
18
|
+
simplecov (~> 0.11.0)
|
19
|
+
term-ansicolor (~> 1.3)
|
20
|
+
thor (~> 0.19.1)
|
21
|
+
tins (~> 1.6.0)
|
21
22
|
docile (1.1.5)
|
22
23
|
em-websocket (0.5.1)
|
23
24
|
eventmachine (>= 0.12.9)
|
@@ -30,7 +31,7 @@ GEM
|
|
30
31
|
net-http-digest_auth (~> 1.4)
|
31
32
|
ffi (1.9.10)
|
32
33
|
formatador (0.2.5)
|
33
|
-
git (1.
|
34
|
+
git (1.3.0)
|
34
35
|
guard (2.13.0)
|
35
36
|
formatador (>= 0.2.4)
|
36
37
|
listen (>= 2.7, <= 4.0)
|
@@ -70,11 +71,11 @@ GEM
|
|
70
71
|
coderay (~> 1.1.0)
|
71
72
|
method_source (~> 0.8.1)
|
72
73
|
slop (~> 3.4)
|
73
|
-
rake (
|
74
|
+
rake (11.1.1)
|
74
75
|
rb-fsevent (0.9.7)
|
75
76
|
rb-inotify (0.9.7)
|
76
77
|
ffi (>= 0.5.0)
|
77
|
-
rubyzip (1.
|
78
|
+
rubyzip (1.2.0)
|
78
79
|
shellany (0.0.1)
|
79
80
|
simplecov (0.11.2)
|
80
81
|
docile (~> 1.1.0)
|
@@ -82,7 +83,10 @@ GEM
|
|
82
83
|
simplecov-html (~> 0.10.0)
|
83
84
|
simplecov-html (0.10.0)
|
84
85
|
slop (3.6.0)
|
86
|
+
term-ansicolor (1.3.2)
|
87
|
+
tins (~> 1.0)
|
85
88
|
thor (0.19.1)
|
89
|
+
tins (1.6.0)
|
86
90
|
yard (0.8.7.6)
|
87
91
|
|
88
92
|
PLATFORMS
|
@@ -90,12 +94,13 @@ PLATFORMS
|
|
90
94
|
|
91
95
|
DEPENDENCIES
|
92
96
|
bundler (~> 1.7)
|
93
|
-
byebug (~>
|
97
|
+
byebug (~> 8.2)
|
98
|
+
coveralls (~> 0.8)
|
94
99
|
guard-livereload (~> 2.5)
|
95
100
|
minitest (~> 5.8)
|
96
101
|
minitest-autotest (~> 1.0)
|
97
102
|
minitest-server (~> 1.0)
|
98
|
-
rake (~>
|
103
|
+
rake (~> 11.1)
|
99
104
|
roku_builder!
|
100
105
|
simplecov (~> 0.11)
|
101
106
|
yard (~> 0.8.7)
|
data/README.md
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
# RokuBuilder
|
2
2
|
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/roku_builder.svg)](https://badge.fury.io/rb/roku_builder)
|
4
|
+
[![Dependency Status](https://gemnasium.com/ViacomInc/roku_builder.svg)](https://gemnasium.com/ViacomInc/roku_builder)
|
5
|
+
[![Build Status](https://travis-ci.org/ViacomInc/roku_builder.svg?branch=master)](https://travis-ci.org/ViacomInc/roku_builder)
|
6
|
+
[![Coverage Status](https://coveralls.io/repos/github/ViacomInc/roku_builder/badge.svg?branch=master)](https://coveralls.io/github/ViacomInc/roku_builder?branch=master)
|
7
|
+
[![Code Climate](https://codeclimate.com/github/ViacomInc/roku_builder/badges/gpa.svg)](https://codeclimate.com/github/ViacomInc/roku_builder)
|
4
8
|
|
5
9
|
A tool to help with Roku Development. Assists with the following roku
|
6
10
|
development tasks:
|
@@ -271,6 +275,7 @@ directory:
|
|
271
275
|
|
272
276
|
* Account for missing folders or files
|
273
277
|
* Increase testing
|
278
|
+
* Config Unit Tests
|
274
279
|
* Intergration Tests
|
275
280
|
* Move RokuBuilder::Controller to RokuBuilder?
|
276
281
|
* Allow start and end delimiter for tests to be configured
|
data/bin/roku
CHANGED
@@ -11,80 +11,79 @@ options = {}
|
|
11
11
|
options[:config] = '~/.roku_config.json'
|
12
12
|
options[:stage] = 'production'
|
13
13
|
options[:update_manifest] = false
|
14
|
-
options[:fetch] = false
|
15
14
|
|
16
15
|
OptionParser.new do |opts|
|
17
16
|
opts.banner = "Usage: roku <command> [options]"
|
18
17
|
|
19
|
-
opts.on("-l", "--sideload", "Command: Sideload an app") do
|
20
|
-
options[:sideload] =
|
18
|
+
opts.on("-l", "--sideload", "Command: Sideload an app") do
|
19
|
+
options[:sideload] = true
|
21
20
|
end
|
22
21
|
|
23
|
-
opts.on("-p", "--package", "Command: Package an app") do
|
24
|
-
options[:package] =
|
22
|
+
opts.on("-p", "--package", "Command: Package an app") do
|
23
|
+
options[:package] = true
|
25
24
|
end
|
26
25
|
|
27
|
-
opts.on("-t", "--test", "Command: Test an app") do
|
28
|
-
options[:test] =
|
26
|
+
opts.on("-t", "--test", "Command: Test an app") do
|
27
|
+
options[:test] = true
|
29
28
|
end
|
30
29
|
|
31
|
-
opts.on("-L", "--deeplink", "Command: Deeplink into app. Requires mgid and type options.") do
|
32
|
-
options[:deeplink] =
|
30
|
+
opts.on("-L", "--deeplink", "Command: Deeplink into app. Requires mgid and type options.") do
|
31
|
+
options[:deeplink] = true
|
33
32
|
end
|
34
33
|
|
35
|
-
opts.on("--configure", "Command: Copy base configuration file to the --config location. Default: '~/.roku_config.json'") do
|
36
|
-
options[:configure] =
|
34
|
+
opts.on("--configure", "Command: Copy base configuration file to the --config location. Default: '~/.roku_config.json'") do
|
35
|
+
options[:configure] = true
|
37
36
|
end
|
38
37
|
|
39
|
-
opts.on("--validate", "Command: Validate configuration'") do
|
40
|
-
options[:validate] =
|
38
|
+
opts.on("--validate", "Command: Validate configuration'") do
|
39
|
+
options[:validate] = true
|
41
40
|
end
|
42
41
|
|
43
|
-
opts.on("-d", "--delete", "Command: Delete the currently sideloaded app") do
|
44
|
-
options[:delete] =
|
42
|
+
opts.on("-d", "--delete", "Command: Delete the currently sideloaded app") do
|
43
|
+
options[:delete] = true
|
45
44
|
end
|
46
45
|
|
47
46
|
opts.on("-N", "--navigate CMD", "Command: send the given command to the roku") do |n|
|
48
47
|
options[:navigate] = n
|
49
48
|
end
|
50
49
|
|
51
|
-
opts.on("-S", "--screencapture", "Command: save a screencapture to the output file/folder") do
|
52
|
-
options[:screencapture] =
|
50
|
+
opts.on("-S", "--screencapture", "Command: save a screencapture to the output file/folder") do
|
51
|
+
options[:screencapture] = true
|
53
52
|
end
|
54
53
|
|
55
54
|
opts.on("-y", "--type TEXT", "Command: type the given text on the roku device") do |t|
|
56
55
|
options[:text] = t
|
57
56
|
end
|
58
57
|
|
59
|
-
opts.on("-b", "--build", "Command: build a zip to be sideloaded") do
|
60
|
-
options[:build] =
|
58
|
+
opts.on("-b", "--build", "Command: build a zip to be sideloaded") do
|
59
|
+
options[:build] = true
|
61
60
|
end
|
62
61
|
|
63
62
|
opts.on("--screen SCREEN", "Command: show a screen") do |s|
|
64
63
|
options[:screen] = s
|
65
64
|
end
|
66
65
|
|
67
|
-
opts.on("--screens", "Command: show possible screens") do
|
68
|
-
options[:screens] =
|
66
|
+
opts.on("--screens", "Command: show possible screens") do
|
67
|
+
options[:screens] = true
|
69
68
|
end
|
70
69
|
|
71
70
|
opts.on("-m", "--monitor TYPE", "Command: run telnet to monitor roku log") do |m|
|
72
71
|
options[:monitor] = m
|
73
72
|
end
|
74
73
|
|
75
|
-
opts.on("-u", "--update-manifest", "Command: update the manifest file") do
|
76
|
-
options[:update] =
|
74
|
+
opts.on("-u", "--update-manifest", "Command: update the manifest file") do
|
75
|
+
options[:update] = true
|
77
76
|
end
|
78
77
|
|
79
78
|
opts.on("-r", "--ref REF", "Git referance to use for sideloading") do |r|
|
80
79
|
options[:ref] = r
|
81
80
|
end
|
82
81
|
|
83
|
-
opts.on("-w", "--working", "Use working directory to sideload or test") do
|
84
|
-
options[:working] =
|
82
|
+
opts.on("-w", "--working", "Use working directory to sideload or test") do
|
83
|
+
options[:working] = true
|
85
84
|
end
|
86
85
|
|
87
|
-
opts.on("-c", "--current", "Use current directory to sideload or test. Overides any project config") do
|
86
|
+
opts.on("-c", "--current", "Use current directory to sideload or test. Overides any project config") do
|
88
87
|
options[:current] = true
|
89
88
|
end
|
90
89
|
|
@@ -93,18 +92,14 @@ OptionParser.new do |opts|
|
|
93
92
|
options[:set_stage] = true
|
94
93
|
end
|
95
94
|
|
96
|
-
opts.on("-M", "--manifest-update", "Update the manifest file while packaging") do
|
95
|
+
opts.on("-M", "--manifest-update", "Update the manifest file while packaging") do
|
97
96
|
options[:update_manifest] = true
|
98
97
|
end
|
99
98
|
|
100
|
-
opts.on("-i", "--inspect", "Print inspection information while packaging") do
|
99
|
+
opts.on("-i", "--inspect", "Print inspection information while packaging") do
|
101
100
|
options[:inspect] = true
|
102
101
|
end
|
103
102
|
|
104
|
-
opts.on("-f", "--fetch", "Preform a `git fetch --all` on the repository before building or sideloading.") do
|
105
|
-
options[:fetch] = true
|
106
|
-
end
|
107
|
-
|
108
103
|
opts.on("-o", "--deeplink-options TYPE", "Additional deeplink options. (eg. a:b, c:d,e:f)") do |o|
|
109
104
|
options[:deeplink_options] = o
|
110
105
|
end
|
@@ -134,15 +129,15 @@ OptionParser.new do |opts|
|
|
134
129
|
options[:in] = i
|
135
130
|
end
|
136
131
|
|
137
|
-
opts.on("-V", "--verbose", "Print Info message") do
|
138
|
-
options[:verbose] =
|
132
|
+
opts.on("-V", "--verbose", "Print Info message") do
|
133
|
+
options[:verbose] = true
|
139
134
|
end
|
140
135
|
|
141
|
-
opts.on("--debug", "Print Debug messages") do
|
142
|
-
options[:debug] =
|
136
|
+
opts.on("--debug", "Print Debug messages") do
|
137
|
+
options[:debug] = true
|
143
138
|
end
|
144
139
|
|
145
|
-
opts.on("-h", "--help", "Show this message") do
|
140
|
+
opts.on("-h", "--help", "Show this message") do
|
146
141
|
puts opts
|
147
142
|
exit
|
148
143
|
end
|
data/config.json.example
CHANGED
@@ -1,25 +1,44 @@
|
|
1
1
|
module RokuBuilder
|
2
2
|
|
3
|
-
MISSING_DEVICES = 1
|
4
|
-
MISSING_DEVICES_DEFAULT = 2
|
5
|
-
DEVICE_DEFAULT_BAD = 3
|
6
|
-
MISSING_PROJECTS = 4
|
7
|
-
MISSING_PROJECTS_DEFAULT = 5
|
8
|
-
PROJECTS_DEFAULT_BAD = 6
|
9
|
-
DEVICE_MISSING_IP = 7
|
10
|
-
DEVICE_MISSING_USER = 8
|
11
|
-
DEVICE_MISSING_PASSWORD = 9
|
12
|
-
PROJECT_MISSING_APP_NAME = 10
|
13
|
-
PROJECT_MISSING_DIRECTORY = 11
|
14
|
-
PROJECT_MISSING_FOLDERS = 12
|
15
|
-
PROJECT_FOLDERS_BAD = 13
|
16
|
-
PROJECT_MISSING_FILES = 14
|
17
|
-
PROJECT_FILES_BAD = 15
|
18
|
-
STAGE_MISSING_BRANCH = 16
|
19
|
-
|
20
3
|
# Load and validate config files.
|
21
4
|
class ConfigManager
|
22
5
|
|
6
|
+
# Load config file and generate intermeidate configs
|
7
|
+
# @param options [Hash] The options hash
|
8
|
+
# @param logger [Logger] system logger
|
9
|
+
# @return [Integer] Return code
|
10
|
+
# @return [Hash] Loaded config
|
11
|
+
# @return [Hash] Intermeidate configs
|
12
|
+
def self.load_config(options:, logger:)
|
13
|
+
config_file = File.expand_path(options[:config])
|
14
|
+
return MISSING_CONFIG unless File.exist?(config_file)
|
15
|
+
code = SUCCESS
|
16
|
+
config = ConfigManager.get_config(config: config_file, logger: logger)
|
17
|
+
return INVALID_CONFIG unless config
|
18
|
+
codes = ConfigValidator.validate_config(config: config)
|
19
|
+
fatal = false
|
20
|
+
warning = false
|
21
|
+
codes.each {|a_code|
|
22
|
+
if a_code > 0
|
23
|
+
logger.fatal "Invalid Config: "+ ConfigValidator.error_codes()[a_code]
|
24
|
+
fatal = true
|
25
|
+
elsif a_code < 0
|
26
|
+
logger.warn "Depricated Config: "+ ConfigValidator.error_codes()[a_code]
|
27
|
+
warning = true
|
28
|
+
elsif a_code == 0 and options[:validate]
|
29
|
+
logger.info "Config Valid"
|
30
|
+
end
|
31
|
+
}
|
32
|
+
return [INVALID_CONFIG, nil, nil] if fatal
|
33
|
+
code = DEPRICATED_CONFIG if warning
|
34
|
+
|
35
|
+
parse_code, configs = ConfigParser.parse_config(options: options, config: config, logger: logger)
|
36
|
+
unless parse_code == SUCCESS
|
37
|
+
return [parse_code, nil, nil]
|
38
|
+
end
|
39
|
+
[code, config, configs]
|
40
|
+
end
|
41
|
+
|
23
42
|
# Loads the roku config from file
|
24
43
|
# @param config [String] path for the roku config
|
25
44
|
# @return [Hash] roku config object
|
@@ -35,75 +54,6 @@ module RokuBuilder
|
|
35
54
|
end
|
36
55
|
end
|
37
56
|
|
38
|
-
# Validates the roku config
|
39
|
-
# @param config [Hash] roku config object
|
40
|
-
# @return [Array] error codes for valid config (see self.error_codes)
|
41
|
-
def self.validate_config(config:, logger:)
|
42
|
-
codes = []
|
43
|
-
codes.push(MISSING_DEVICES) if not config[:devices]
|
44
|
-
codes.push(MISSING_DEVICES_DEFAULT) if config[:devices] and not config[:devices][:default]
|
45
|
-
codes.push(DEVICE_DEFAULT_BAD) if config[:devices] and config[:devices][:default] and not config[:devices][:default].is_a?(Symbol)
|
46
|
-
codes.push(MISSING_PROJECTS) if not config[:projects]
|
47
|
-
codes.push(MISSING_PROJECTS_DEFAULT) if config[:projects] and not config[:projects][:default]
|
48
|
-
codes.push(MISSING_PROJECTS_DEFAULT) if config[:projects] and config[:projects][:default] == "<project id>".to_sym
|
49
|
-
codes.push(PROJECTS_DEFAULT_BAD) if config[:projects] and config[:projects][:default] and not config[:projects][:default].is_a?(Symbol)
|
50
|
-
if config[:devices]
|
51
|
-
config[:devices].each {|k,v|
|
52
|
-
next if k == :default
|
53
|
-
codes.push(DEVICE_MISSING_IP) if not v[:ip]
|
54
|
-
codes.push(DEVICE_MISSING_IP) if v[:ip] == "xxx.xxx.xxx.xxx"
|
55
|
-
codes.push(DEVICE_MISSING_IP) if v[:ip] == ""
|
56
|
-
codes.push(DEVICE_MISSING_USER) if not v[:user]
|
57
|
-
codes.push(DEVICE_MISSING_USER) if v[:user] == "<username>"
|
58
|
-
codes.push(DEVICE_MISSING_USER) if v[:user] == ""
|
59
|
-
codes.push(DEVICE_MISSING_PASSWORD) if not v[:password]
|
60
|
-
codes.push(DEVICE_MISSING_PASSWORD) if v[:password] == "<password>"
|
61
|
-
codes.push(DEVICE_MISSING_PASSWORD) if v[:password] == ""
|
62
|
-
}
|
63
|
-
end
|
64
|
-
if config[:projects]
|
65
|
-
config[:projects].each {|k,v|
|
66
|
-
next if k == :default
|
67
|
-
codes.push(PROJECT_MISSING_APP_NAME) if not v[:app_name]
|
68
|
-
codes.push(PROJECT_MISSING_DIRECTORY) if not v[:directory]
|
69
|
-
codes.push(PROJECT_MISSING_FOLDERS) if not v[:folders]
|
70
|
-
codes.push(PROJECT_FOLDERS_BAD) if v[:folders] and not v[:folders].is_a?(Array)
|
71
|
-
codes.push(PROJECT_MISSING_FILES) if not v[:files]
|
72
|
-
codes.push(PROJECT_FILES_BAD) if v[:files] and not v[:files].is_a?(Array)
|
73
|
-
v[:stages].each {|k,v|
|
74
|
-
codes.push(STAGE_MISSING_BRANCH) if not v[:branch]
|
75
|
-
}
|
76
|
-
}
|
77
|
-
end
|
78
|
-
codes.push(0) if codes.empty?
|
79
|
-
codes
|
80
|
-
end
|
81
|
-
|
82
|
-
# Error code messages for config validation
|
83
|
-
# @return [Array] error code messages
|
84
|
-
def self.error_codes()
|
85
|
-
[
|
86
|
-
#===============FATAL ERRORS===============#
|
87
|
-
"Valid Config.",
|
88
|
-
"Devices config is missing.",
|
89
|
-
"Devices default is missing.",
|
90
|
-
"Devices default is not a hash.",
|
91
|
-
"Projects config is missing.",
|
92
|
-
"Projects default is missing.", #5
|
93
|
-
"Projects default is not a hash.",
|
94
|
-
"A device config is missing its IP address.",
|
95
|
-
"A device config is missing its username.",
|
96
|
-
"A device config is missing its password.",
|
97
|
-
"A project config is missing its app_name.", #10
|
98
|
-
"A project config is missing its directorty.",
|
99
|
-
"A project config is missing its folders.",
|
100
|
-
"A project config's folders is not an array.",
|
101
|
-
"A project config is missing its files.",
|
102
|
-
"A project config's files is not an array.", #15
|
103
|
-
"A project stage is missing its branch."
|
104
|
-
#===============WARNINGS===============#
|
105
|
-
]
|
106
|
-
end
|
107
57
|
|
108
58
|
# Edit the roku config
|
109
59
|
# @param config [String] path for the roku config
|
@@ -112,46 +62,61 @@ module RokuBuilder
|
|
112
62
|
# @param project [String] which project to use
|
113
63
|
# @param stage[String] which stage to use
|
114
64
|
# @return [Boolean] success
|
115
|
-
def self.edit_config(config:, options:,
|
65
|
+
def self.edit_config(config:, options:, logger:)
|
116
66
|
config_object = get_config(config: config, logger: logger)
|
117
67
|
return false unless config_object
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
unless
|
124
|
-
|
125
|
-
|
126
|
-
device
|
127
|
-
|
128
|
-
unless stage
|
129
|
-
stage = :production
|
130
|
-
else
|
131
|
-
stage = stage.to_sym
|
132
|
-
end
|
133
|
-
changes = {}
|
134
|
-
opts = options.split(/,\s*/)
|
135
|
-
opts.each do |opt|
|
136
|
-
opt = opt.split(":")
|
137
|
-
key = opt.shift.to_sym
|
138
|
-
value = opt.join(":")
|
139
|
-
changes[key] = value
|
140
|
-
end
|
141
|
-
changes.each {|key,value|
|
142
|
-
if [:ip, :user, :password].include?(key)
|
143
|
-
config_object[:devices][device][key] = value
|
144
|
-
elsif [:directory, :app_name].include?(key) #:folders, :files
|
145
|
-
config_object[:projects][project][key] = value
|
146
|
-
elsif [:branch]
|
147
|
-
config_object[:projects][project][:stages][stage][key] = value
|
148
|
-
end
|
68
|
+
project = options[:project].to_sym if options[:project]
|
69
|
+
project = config_object[:projects][:default] unless options[:project]
|
70
|
+
device = options[:device].to_sym if options[:device]
|
71
|
+
device = config_object[:devices][:default] unless options[:device]
|
72
|
+
stage = options[:stage].to_sym if options[:stage]
|
73
|
+
stage = :production unless options[:stage]
|
74
|
+
state = {
|
75
|
+
project: project,
|
76
|
+
device: device,
|
77
|
+
stage: stage
|
149
78
|
}
|
79
|
+
apply_options(config_object: config_object, options: options[:edit_params], state: state)
|
150
80
|
config_string = JSON.pretty_generate(config_object)
|
151
81
|
file = File.open(config, "w")
|
152
82
|
file.write(config_string)
|
153
83
|
file.close
|
154
84
|
return true
|
155
85
|
end
|
86
|
+
|
87
|
+
# Apply the changes in the options string to the config object
|
88
|
+
# @param config_object [Hash] The config loaded from file
|
89
|
+
# @param options [String] The string of options passed in by the user
|
90
|
+
# @param state [Hash] The state of the config the user is editing
|
91
|
+
def self.apply_options(config_object:, options:, state:)
|
92
|
+
changes = Util.options_parse(options: options)
|
93
|
+
changes.each {|key,value|
|
94
|
+
if [:ip, :user, :password].include?(key)
|
95
|
+
config_object[:devices][state[:device]][key] = value
|
96
|
+
elsif [:directory, :app_name].include?(key) #:folders, :files
|
97
|
+
config_object[:projects][state[:project]][key] = value
|
98
|
+
elsif [:branch].include?(key)
|
99
|
+
config_object[:projects][state[:project]][:stages][state[:stage]][key] = value
|
100
|
+
end
|
101
|
+
}
|
102
|
+
end
|
103
|
+
private_class_method :apply_options
|
104
|
+
|
105
|
+
# Update the intermeidate configs
|
106
|
+
# @param configs [Hash] Intermeidate configs hash
|
107
|
+
# @param options [Hash] Options hash
|
108
|
+
# @return [Hash] New intermeidate configs hash
|
109
|
+
def self.update_configs(configs:, options:)
|
110
|
+
if options[:build_version]
|
111
|
+
configs[:package_config][:app_name_version] = "#{configs[:project_config][:app_name]} - #{configs[:stage]} - #{options[:build_version]}" if configs[:package_config]
|
112
|
+
unless options[:outfile]
|
113
|
+
pathname = File.join(options[:out_folder], "#{configs[:project_config][:app_name]}_#{configs[:stage]}_#{options[:build_version]}")
|
114
|
+
configs[:package_config][:out_file] = pathname+".pkg" if configs[:package_config]
|
115
|
+
configs[:build_config][:outfile] = pathname+".zip" if configs[:build_config]
|
116
|
+
configs[:inspect_config][:pkg] = configs[:package_config][:out_file] if configs[:inspect_config] and configs[:package_config]
|
117
|
+
end
|
118
|
+
end
|
119
|
+
return configs
|
120
|
+
end
|
156
121
|
end
|
157
122
|
end
|
@@ -0,0 +1,192 @@
|
|
1
|
+
module RokuBuilder
|
2
|
+
|
3
|
+
# Contains methods that will parse the loaded config and generate
|
4
|
+
# intermeidate configs for each of the tools.
|
5
|
+
class ConfigParser
|
6
|
+
|
7
|
+
# Parse config and generate intermeidate configs
|
8
|
+
# @param options [Hash] The options hash
|
9
|
+
# @param config [Hash] The loaded config hash
|
10
|
+
# @param logger [Logger] system logger
|
11
|
+
# @return [Integer] Return code
|
12
|
+
# @return [Hash] Intermeidate configs
|
13
|
+
def self.parse_config(options:, config:, logger:)
|
14
|
+
configs = {}
|
15
|
+
#set device
|
16
|
+
unless options[:device]
|
17
|
+
options[:device] = config[:devices][:default]
|
18
|
+
end
|
19
|
+
#set project
|
20
|
+
setup_project(config: config, options: options)
|
21
|
+
#set outfile
|
22
|
+
setup_outfile(options: options)
|
23
|
+
# Create Device Config
|
24
|
+
configs[:device_config] = config[:devices][options[:device].to_sym]
|
25
|
+
return [UNKNOWN_DEVICE, nil, nil] unless configs[:device_config]
|
26
|
+
configs[:device_config][:logger] = logger
|
27
|
+
project_config = setup_project_config(config: config, options: options)
|
28
|
+
return [UNKNOWN_PROJECT, nil, nil] unless project_config
|
29
|
+
configs[:project_config] = project_config
|
30
|
+
stage = options[:stage].to_sym
|
31
|
+
return [UNKNOWN_STAGE, nil, nil] unless project_config[:stages][stage]
|
32
|
+
configs[:stage] = stage
|
33
|
+
branch = project_config[:stages][stage][:branch]
|
34
|
+
branch = options[:ref] if options[:ref]
|
35
|
+
branch = nil if options[:current]
|
36
|
+
branch = nil if options[:working]
|
37
|
+
setup_sideload_config(configs: configs, options: options, branch: branch)
|
38
|
+
setup_package_config(configs: configs, options: options, stage: stage)
|
39
|
+
setup_simple_configs(configs: configs, options: options, logger: logger)
|
40
|
+
return [SUCCESS, configs]
|
41
|
+
end
|
42
|
+
|
43
|
+
# Pick or choose the project being used
|
44
|
+
# @param config [Hash] The loaded config hash
|
45
|
+
# @param options [Hash] The options hash
|
46
|
+
def self.setup_project(config:, options:)
|
47
|
+
if options[:current] or not options[:project]
|
48
|
+
path = Controller.system(command: "pwd")
|
49
|
+
project = nil
|
50
|
+
config[:projects].each_pair {|key,value|
|
51
|
+
if value.is_a?(Hash)
|
52
|
+
repo_path = Pathname.new(value[:directory]).realdirpath.to_s
|
53
|
+
if path.start_with?(repo_path)
|
54
|
+
project = key
|
55
|
+
break
|
56
|
+
end
|
57
|
+
end
|
58
|
+
}
|
59
|
+
if project
|
60
|
+
options[:project] = project
|
61
|
+
else
|
62
|
+
options[:project] = config[:projects][:default]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
private_class_method :setup_project
|
67
|
+
|
68
|
+
# Setup the out folder/file options
|
69
|
+
# @param options [Hash] The options hash
|
70
|
+
def self.setup_outfile(options:)
|
71
|
+
options[:out_folder] = nil
|
72
|
+
options[:out_file] = nil
|
73
|
+
if options[:out]
|
74
|
+
if options[:out].end_with?(".zip") or options[:out].end_with?(".pkg") or options[:out].end_with?(".jpg")
|
75
|
+
options[:out_folder], options[:out_file] = Pathname.new(options[:out]).split.map{|p| p.to_s}
|
76
|
+
else
|
77
|
+
options[:out_folder] = options[:out]
|
78
|
+
end
|
79
|
+
end
|
80
|
+
unless options[:out_folder]
|
81
|
+
options[:out_folder] = "/tmp"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
private_class_method :setup_outfile
|
85
|
+
|
86
|
+
# Setup the project config with the chosen project
|
87
|
+
# @param config [Hash] The loaded config hash
|
88
|
+
# @param options [Hash] The options hash
|
89
|
+
# @return [Hash] The project config hash
|
90
|
+
def self.setup_project_config(config:, options:)
|
91
|
+
#Create Project Config
|
92
|
+
project_config = {}
|
93
|
+
if options[:current]
|
94
|
+
pwd = Controller.system(command: "pwd")
|
95
|
+
return [MISSING_MANIFEST, nil, nil] unless File.exist?(File.join(pwd, "manifest"))
|
96
|
+
project_config = {
|
97
|
+
directory: pwd,
|
98
|
+
folders: nil,
|
99
|
+
files: nil,
|
100
|
+
stages: { production: { branch: nil } }
|
101
|
+
}
|
102
|
+
else
|
103
|
+
project_config = config[:projects][options[:project].to_sym]
|
104
|
+
end
|
105
|
+
project_config
|
106
|
+
end
|
107
|
+
private_class_method :setup_project_config
|
108
|
+
|
109
|
+
# Setup config hashes for sideloading
|
110
|
+
# @param configs [Hash] The parsed configs hash
|
111
|
+
# @param options [Hash] The options hash
|
112
|
+
# @param branch [String] the branch to sideload
|
113
|
+
def self.setup_sideload_config(configs:, options:, branch:)
|
114
|
+
root_dir = configs[:project_config][:directory]
|
115
|
+
# Create Sideload Config
|
116
|
+
configs[:sideload_config] = {
|
117
|
+
root_dir: root_dir,
|
118
|
+
branch: branch,
|
119
|
+
update_manifest: options[:update_manifest],
|
120
|
+
folders: configs[:project_config][:folders],
|
121
|
+
files: configs[:project_config][:files]
|
122
|
+
}
|
123
|
+
# Create Build Config
|
124
|
+
configs[:build_config] = {
|
125
|
+
root_dir: root_dir,
|
126
|
+
branch: branch,
|
127
|
+
folders: configs[:project_config][:folders],
|
128
|
+
files: configs[:project_config][:files]
|
129
|
+
}
|
130
|
+
end
|
131
|
+
private_class_method :setup_sideload_config
|
132
|
+
|
133
|
+
# Setup config hashes for packaging
|
134
|
+
# @param configs [Hash] The parsed configs hash
|
135
|
+
# @param options [Hash] The options hash
|
136
|
+
# @param stage [Symbol] The stage to package
|
137
|
+
def self.setup_package_config(configs:, options:, stage:)
|
138
|
+
if options[:package]
|
139
|
+
# Create Key Config
|
140
|
+
configs[:key] = configs[:project_config][:stages][stage][:key]
|
141
|
+
# Create Package Config
|
142
|
+
configs[:package_config] = {
|
143
|
+
password: configs[:key][:password],
|
144
|
+
app_name_version: "#{configs[:project_config][:app_name]} - #{stage}"
|
145
|
+
}
|
146
|
+
if options[:out_file]
|
147
|
+
configs[:package_config][:out_file] = File.join(options[:out_folder], options[:out_file])
|
148
|
+
end
|
149
|
+
# Create Inspector Config
|
150
|
+
configs[:inspect_config] = {
|
151
|
+
pkg: configs[:package_config][:out_file],
|
152
|
+
password: configs[:key][:password]
|
153
|
+
}
|
154
|
+
end
|
155
|
+
end
|
156
|
+
private_class_method :setup_package_config
|
157
|
+
|
158
|
+
# Setup other configs
|
159
|
+
# @param configs [Hash] The parsed configs hash
|
160
|
+
# @param options [Hash] The options hash
|
161
|
+
# @param logger [Logger] System logger
|
162
|
+
def self.setup_simple_configs(configs:, options:, logger:)
|
163
|
+
# Create Manifest Config
|
164
|
+
configs[:manifest_config] = {
|
165
|
+
root_dir: configs[:project_config][:directory]
|
166
|
+
}
|
167
|
+
# Create Deeplink Config
|
168
|
+
configs[:deeplink_config] ={options: options[:deeplink_options]}
|
169
|
+
# Create Monitor Config
|
170
|
+
if options[:monitor]
|
171
|
+
configs[:monitor_config] = {type: options[:monitor].to_sym}
|
172
|
+
end
|
173
|
+
# Create Navigate Config
|
174
|
+
if options[:navigate]
|
175
|
+
configs[:navigate_config] = {command: options[:navigate].to_sym}
|
176
|
+
end
|
177
|
+
# Create Text Config
|
178
|
+
configs[:text_config] = {text: options[:text]}
|
179
|
+
# Create Test Config
|
180
|
+
configs[:test_config] = {sideload_config: configs[:sideload_config]}
|
181
|
+
#Create screencapture config
|
182
|
+
configs[:screencapture_config] = {
|
183
|
+
out_folder: options[:out_folder],
|
184
|
+
out_file: options[:out_file]
|
185
|
+
}
|
186
|
+
if options[:screen]
|
187
|
+
configs[:screen_config] = {type: options[:screen].to_sym}
|
188
|
+
end
|
189
|
+
end
|
190
|
+
private_class_method :setup_simple_configs
|
191
|
+
end
|
192
|
+
end
|