roku_builder 3.3.3 → 3.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +1158 -0
  4. data/.travis.yml +3 -0
  5. data/Gemfile.lock +19 -14
  6. data/README.md +5 -0
  7. data/bin/roku +32 -37
  8. data/config.json.example +2 -2
  9. data/lib/roku_builder/config_manager.rb +83 -118
  10. data/lib/roku_builder/config_parser.rb +192 -0
  11. data/lib/roku_builder/config_validator.rb +125 -0
  12. data/lib/roku_builder/controller.rb +97 -484
  13. data/lib/roku_builder/controller_commands.rb +112 -0
  14. data/lib/roku_builder/error_handler.rb +116 -0
  15. data/lib/roku_builder/inspector.rb +5 -18
  16. data/lib/roku_builder/keyer.rb +3 -11
  17. data/lib/roku_builder/linker.rb +3 -15
  18. data/lib/roku_builder/loader.rb +52 -89
  19. data/lib/roku_builder/manifest_manager.rb +2 -3
  20. data/lib/roku_builder/monitor.rb +15 -12
  21. data/lib/roku_builder/navigator.rb +2 -10
  22. data/lib/roku_builder/packager.rb +1 -7
  23. data/lib/roku_builder/tester.rb +1 -0
  24. data/lib/roku_builder/util.rb +39 -0
  25. data/lib/roku_builder/version.rb +1 -1
  26. data/lib/roku_builder.rb +96 -1
  27. data/roku_builder.gemspec +5 -4
  28. data/tests/roku_builder/config_manager_test.rb +80 -241
  29. data/tests/roku_builder/{controller_config_test.rb → config_parser_test.rb} +5 -5
  30. data/tests/roku_builder/config_validator_test.rb +158 -0
  31. data/tests/roku_builder/controller_commands_test.rb +304 -0
  32. data/tests/roku_builder/controller_test.rb +61 -620
  33. data/tests/roku_builder/error_handler_test.rb +76 -0
  34. data/tests/roku_builder/inspector_test.rb +3 -0
  35. data/tests/roku_builder/keyer_test.rb +3 -2
  36. data/tests/roku_builder/linker_test.rb +2 -1
  37. data/tests/roku_builder/loader_test.rb +2 -0
  38. data/tests/roku_builder/manifest_manager_test.rb +3 -6
  39. data/tests/roku_builder/monitor_test.rb +5 -13
  40. data/tests/roku_builder/navigator_test.rb +2 -0
  41. data/tests/roku_builder/test_helper.rb +38 -0
  42. metadata +34 -11
data/.travis.yml ADDED
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - "2.2.1"
data/Gemfile.lock CHANGED
@@ -1,23 +1,24 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- roku_builder (3.3.3)
4
+ roku_builder (3.3.4)
5
5
  faraday (~> 0.9)
6
6
  faraday-digestauth (~> 0.2)
7
- git (~> 1.2.9)
7
+ git (~> 1.3)
8
8
  net-ping (~> 1.7)
9
- rubyzip (~> 1.1)
9
+ rubyzip (~> 1.2)
10
10
 
11
11
  GEM
12
12
  remote: https://rubygems.org/
13
13
  specs:
14
- byebug (3.5.1)
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
- columnize (0.9.0)
20
- debugger-linecache (1.2.0)
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.2.9.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 (10.5.0)
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.1.7)
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 (~> 3.5)
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 (~> 10.0)
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 |s|
20
- options[:sideload] = s
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 |p|
24
- options[:package] = p
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 |t|
28
- options[:test] = t
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 |d|
32
- options[:deeplink] = d
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 |c|
36
- options[:configure] = c
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 |v|
40
- options[:validate] = v
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 |d|
44
- options[:delete] = d
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 |s|
52
- options[:screencapture] = s
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 |b|
60
- options[:build] = b
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 |s|
68
- options[:screens] = s
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 |u|
76
- options[:update] = u
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 |w|
84
- options[:working] = w
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 |w|
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 |n|
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 |n|
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 |v|
138
- options[:verbose] = v
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 |d|
142
- options[:debug] = d
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 |h|
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,7 +1,7 @@
1
1
  {
2
2
  "devices": {
3
- "default": "roku",
4
- "roku": {
3
+ "default": "<device_id>",
4
+ "<device_id>": {
5
5
  "ip": "xxx.xxx.xxx.xxx",
6
6
  "user": "<username>",
7
7
  "password": "<password>"
@@ -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:, device:, project:, stage:, logger:)
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
- unless project
119
- project = config_object[:projects][:default]
120
- else
121
- project = project.to_sym
122
- end
123
- unless device
124
- device = config_object[:devices][:default]
125
- else
126
- device = device.to_sym
127
- end
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