roku_builder 3.5.0 → 3.6.0
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.
- checksums.yaml +4 -4
- data/.travis.yml +1 -1
- data/Gemfile.lock +1 -1
- data/config.json.example +1 -0
- data/lib/roku_builder/config_parser.rb +12 -4
- data/lib/roku_builder/controller.rb +7 -3
- data/lib/roku_builder/controller_commands.rb +8 -7
- data/lib/roku_builder/loader.rb +35 -26
- data/lib/roku_builder/manifest_manager.rb +11 -2
- data/lib/roku_builder/tester.rb +7 -5
- data/lib/roku_builder/version.rb +1 -1
- data/lib/roku_builder.rb +3 -0
- data/roku_builder.gemspec +1 -1
- data/tests/roku_builder/controller_commands_test.rb +4 -4
- data/tests/roku_builder/controller_test.rb +1 -2
- data/tests/roku_builder/loader_test.rb +24 -10
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 878733ac2055fcbfa7fb162abf1f36a3d8e200c7
|
4
|
+
data.tar.gz: ee4a6a97eb48e0befd1e9dd5ec8e542396411f9b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bb15a8cdf99cdf04716c9ca95c8b531a492f1eff3632f7a663d0e061f34dcc5e5951b10d182bca3fe0cec130201010f0dc32f7a8fbbbb13890666ba9c3918fbb
|
7
|
+
data.tar.gz: 5894aeed3e103c46480cce8061b3b2fbd1a469c3f2391d6e72420a6d4f8531485d4ef15692b158959a30fd3529ecf8479129e558d4a0f03700e09ae26feb0d17
|
data/.travis.yml
CHANGED
data/Gemfile.lock
CHANGED
data/config.json.example
CHANGED
@@ -140,16 +140,24 @@ module RokuBuilder
|
|
140
140
|
# @param branch [String] the branch to sideload
|
141
141
|
def self.setup_sideload_config(configs:, options:)
|
142
142
|
root_dir = configs[:project_config][:directory]
|
143
|
+
content = {
|
144
|
+
folders: configs[:project_config][:folders],
|
145
|
+
files: configs[:project_config][:files],
|
146
|
+
}
|
147
|
+
all_commands = options.keys & Controller.commands
|
148
|
+
if Controller.exclude_commands.include?(all_commands.first)
|
149
|
+
content[:excludes] = configs[:project_config][:excludes]
|
150
|
+
end
|
151
|
+
|
143
152
|
# Create Sideload Config
|
144
153
|
configs[:sideload_config] = {
|
145
154
|
update_manifest: options[:update_manifest],
|
146
|
-
|
147
|
-
|
155
|
+
infile: options[:in],
|
156
|
+
content: content
|
148
157
|
}
|
149
158
|
# Create Build Config
|
150
159
|
configs[:build_config] = {
|
151
|
-
|
152
|
-
files: configs[:project_config][:files]
|
160
|
+
content: content
|
153
161
|
}
|
154
162
|
configs[:init_params][:loader] = {
|
155
163
|
root_dir: root_dir
|
@@ -164,7 +164,6 @@ module RokuBuilder
|
|
164
164
|
:navigate, :text, :build, :monitor, :update, :screencapture, :key, :screen,
|
165
165
|
:screens]
|
166
166
|
end
|
167
|
-
private_class_method :commands
|
168
167
|
|
169
168
|
# List of depricated options
|
170
169
|
# @return [Hash] Hash of depricated options and the warning message for each
|
@@ -175,7 +174,7 @@ module RokuBuilder
|
|
175
174
|
# List of source options
|
176
175
|
# @return [Array<Symbol>] List of source symbols that can be used in the options hash
|
177
176
|
def self.sources
|
178
|
-
[:ref, :set_stage, :working, :current]
|
177
|
+
[:ref, :set_stage, :working, :current, :in]
|
179
178
|
end
|
180
179
|
|
181
180
|
# List of commands requiring a source option
|
@@ -183,7 +182,12 @@ module RokuBuilder
|
|
183
182
|
def self.source_commands
|
184
183
|
[:sideload, :package, :test, :build, :key]
|
185
184
|
end
|
186
|
-
|
185
|
+
|
186
|
+
# List of commands the activate the exclude files
|
187
|
+
# @return [Array<Symbol] List of commands the will activate the exclude files lists
|
188
|
+
def self.exclude_commands
|
189
|
+
[:build, :package]
|
190
|
+
end
|
187
191
|
|
188
192
|
|
189
193
|
# Configure the gem
|
@@ -39,15 +39,16 @@ module RokuBuilder
|
|
39
39
|
config = configs[:device_config].dup
|
40
40
|
config[:init_params] = configs[:init_params][:loader]
|
41
41
|
stager = Stager.new(**configs[:stage_config])
|
42
|
-
success =
|
42
|
+
success = nil
|
43
43
|
if stager.stage
|
44
44
|
loader = Loader.new(**config)
|
45
|
-
success = loader.sideload(**configs[:sideload_config])
|
45
|
+
success, version = loader.sideload(**configs[:sideload_config])
|
46
46
|
end
|
47
47
|
stager.unstage
|
48
|
-
|
49
|
-
|
50
|
-
|
48
|
+
unless success == FAILED_SIDELOAD
|
49
|
+
logger.info "App Sideloaded; staged using #{stager.method}"
|
50
|
+
end
|
51
|
+
success
|
51
52
|
end
|
52
53
|
# Run Package
|
53
54
|
# @param options [Hash] user options
|
@@ -65,8 +66,8 @@ module RokuBuilder
|
|
65
66
|
logger.warn "Packaging working directory" if options[:working]
|
66
67
|
if stager.stage
|
67
68
|
# Sideload #
|
68
|
-
build_version = loader.sideload(**configs[:sideload_config])
|
69
|
-
return
|
69
|
+
code, build_version = loader.sideload(**configs[:sideload_config])
|
70
|
+
return code unless code = SUCCESS
|
70
71
|
# Key #
|
71
72
|
success = keyer.rekey(**configs[:key])
|
72
73
|
logger.info "Key did not change" unless success
|
data/lib/roku_builder/loader.rb
CHANGED
@@ -11,19 +11,24 @@ module RokuBuilder
|
|
11
11
|
|
12
12
|
# Sideload an app onto a roku device
|
13
13
|
# @param root_dir [String] Path to the root directory of the roku app
|
14
|
-
# @param
|
15
|
-
# @param files [Array<String>] Array of files to be sideloaded. Pass nil to send all files. Default: nil
|
14
|
+
# @param content [Hash] Hash containing arrays for folder, files, and excludes. Default: nil
|
16
15
|
# @return [String] Build version on success, nil otherwise
|
17
|
-
def sideload(update_manifest: false,
|
18
|
-
result =
|
19
|
-
|
20
|
-
build_version =
|
21
|
-
if
|
22
|
-
build_version = ManifestManager.
|
16
|
+
def sideload(update_manifest: false, content: nil, infile: nil)
|
17
|
+
result = FAILED_SIDELOAD
|
18
|
+
outfile = nil
|
19
|
+
build_version = nil
|
20
|
+
if infile
|
21
|
+
build_version = ManifestManager.build_version(root_dir: infile)
|
22
|
+
outfile = infile
|
23
23
|
else
|
24
|
-
|
24
|
+
# Update manifest
|
25
|
+
if update_manifest
|
26
|
+
build_version = ManifestManager.update_build(root_dir: @root_dir)
|
27
|
+
else
|
28
|
+
build_version = ManifestManager.build_version(root_dir: @root_dir)
|
29
|
+
end
|
30
|
+
outfile = build(build_version: build_version, content: content)
|
25
31
|
end
|
26
|
-
outfile = build(build_version: build_version, folders: folders, files: files)
|
27
32
|
path = "/plugin_install"
|
28
33
|
# Connect to roku and upload file
|
29
34
|
conn = multipart_connection
|
@@ -33,9 +38,10 @@ module RokuBuilder
|
|
33
38
|
}
|
34
39
|
response = conn.post path, payload
|
35
40
|
# Cleanup
|
36
|
-
File.delete(outfile)
|
37
|
-
result =
|
38
|
-
|
41
|
+
File.delete(outfile) unless infile
|
42
|
+
result = SUCCESS if response.status==200 and response.body=~/Install Success/
|
43
|
+
result = IDENTICAL_SIDELOAD if response.status==200 and response.body=~/Identical to previous version/
|
44
|
+
[result, build_version]
|
39
45
|
end
|
40
46
|
|
41
47
|
|
@@ -43,30 +49,31 @@ module RokuBuilder
|
|
43
49
|
# @param root_dir [String] Path to the root directory of the roku app
|
44
50
|
# @param build_version [String] Version to assigne to the build. If nil will pull the build version form the manifest. Default: nil
|
45
51
|
# @param outfile [String] Path for the output file. If nil will create a file in /tmp. Default: nil
|
46
|
-
# @param
|
47
|
-
# @param files [Array<String>] Array of files to be sideloaded. Pass nil to send all files. Default: nil
|
52
|
+
# @param content [Hash] Hash containing arrays for folder, files, and excludes. Default: nil
|
48
53
|
# @return [String] Path of the build
|
49
|
-
def build(build_version: nil, outfile: nil,
|
54
|
+
def build(build_version: nil, outfile: nil, content: nil)
|
50
55
|
build_version = ManifestManager.build_version(root_dir: @root_dir) unless build_version
|
51
|
-
|
52
|
-
|
56
|
+
content ||= {}
|
57
|
+
unless content and content[:folders]
|
58
|
+
content[:folders] = Dir.entries(@root_dir).select {|entry| File.directory? File.join(@root_dir, entry) and !(entry =='.' || entry == '..') }
|
53
59
|
end
|
54
|
-
unless files
|
55
|
-
files = Dir.entries(@root_dir).select {|entry| File.file? File.join(@root_dir, entry)}
|
60
|
+
unless content and content[:files]
|
61
|
+
content[:files] = Dir.entries(@root_dir).select {|entry| File.file? File.join(@root_dir, entry)}
|
56
62
|
end
|
63
|
+
content[:excludes] = [] unless content and content[:excludes]
|
57
64
|
outfile = "/tmp/build_#{build_version}.zip" unless outfile
|
58
65
|
File.delete(outfile) if File.exist?(outfile)
|
59
66
|
io = Zip::File.open(outfile, Zip::File::CREATE)
|
60
67
|
# Add folders to zip
|
61
|
-
folders.each do |folder|
|
68
|
+
content[:folders].each do |folder|
|
62
69
|
base_folder = File.join(@root_dir, folder)
|
63
70
|
entries = Dir.entries(base_folder)
|
64
71
|
entries.delete(".")
|
65
72
|
entries.delete("..")
|
66
|
-
writeEntries(@root_dir, entries, folder, io)
|
73
|
+
writeEntries(@root_dir, entries, folder, content[:excludes], io)
|
67
74
|
end
|
68
75
|
# Add file to zip
|
69
|
-
writeEntries(@root_dir, files, "", io)
|
76
|
+
writeEntries(@root_dir, content[:files], "", content[:excludes], io)
|
70
77
|
io.close()
|
71
78
|
outfile
|
72
79
|
end
|
@@ -95,16 +102,18 @@ module RokuBuilder
|
|
95
102
|
# @param entries [Array<String>] Array of file paths of files/directories to store in the zip archive
|
96
103
|
# @param path [String] The path of the current directory starting at the root directory
|
97
104
|
# @param io [IO] zip IO object
|
98
|
-
def writeEntries(root_dir, entries, path, io)
|
105
|
+
def writeEntries(root_dir, entries, path, excludes, io)
|
99
106
|
entries.each { |e|
|
100
107
|
zipFilePath = path == "" ? e : File.join(path, e)
|
101
108
|
diskFilePath = File.join(root_dir, zipFilePath)
|
102
109
|
if File.directory?(diskFilePath)
|
103
110
|
io.mkdir(zipFilePath)
|
104
111
|
subdir =Dir.entries(diskFilePath); subdir.delete("."); subdir.delete("..")
|
105
|
-
writeEntries(root_dir, subdir, zipFilePath, io)
|
112
|
+
writeEntries(root_dir, subdir, zipFilePath, excludes, io)
|
106
113
|
else
|
107
|
-
|
114
|
+
unless excludes.include?(zipFilePath)
|
115
|
+
io.get_output_stream(zipFilePath) { |f| f.puts(File.open(diskFilePath, "rb").read()) }
|
116
|
+
end
|
108
117
|
end
|
109
118
|
}
|
110
119
|
end
|
@@ -47,14 +47,23 @@ module RokuBuilder
|
|
47
47
|
# @param root_dir [String] Path to the root directory for the app
|
48
48
|
# @return [String] Build version on success, empty string otherwise
|
49
49
|
def self.build_version(root_dir:)
|
50
|
-
path = File.join(root_dir, 'manifest')
|
51
50
|
build_version = ""
|
52
|
-
|
51
|
+
get_version = lambda { |file|
|
53
52
|
file.each_line do |line|
|
54
53
|
if line.include?("build_version")
|
55
54
|
build_version = line.split("=")[1].chomp
|
56
55
|
end
|
57
56
|
end
|
57
|
+
}
|
58
|
+
if File.directory?(root_dir)
|
59
|
+
path = File.join(root_dir, 'manifest')
|
60
|
+
build_version = ""
|
61
|
+
File.open(path, 'r', &get_version)
|
62
|
+
elsif File.extname(root_dir) == ".zip"
|
63
|
+
Zip::File.open(root_dir) do |zip_file|
|
64
|
+
entry = zip_file.glob("manifest").first
|
65
|
+
entry.get_input_stream(&get_version)
|
66
|
+
end
|
58
67
|
end
|
59
68
|
build_version
|
60
69
|
end
|
data/lib/roku_builder/tester.rb
CHANGED
@@ -21,13 +21,15 @@ module RokuBuilder
|
|
21
21
|
|
22
22
|
loader = Loader.new(**@device_config)
|
23
23
|
connection = Net::Telnet.new(telnet_config)
|
24
|
-
loader.sideload(**sideload_config)
|
24
|
+
code, _build_version = loader.sideload(**sideload_config)
|
25
25
|
|
26
|
-
|
27
|
-
|
28
|
-
|
26
|
+
if code = SUCCESS
|
27
|
+
in_tests = false
|
28
|
+
connection.waitfor(@end_reg) do |txt|
|
29
|
+
in_tests = handle_text(txt: txt, in_tests: in_tests)
|
30
|
+
end
|
31
|
+
connection.puts("cont\n")
|
29
32
|
end
|
30
|
-
connection.puts("cont\n")
|
31
33
|
end
|
32
34
|
|
33
35
|
private
|
data/lib/roku_builder/version.rb
CHANGED
data/lib/roku_builder.rb
CHANGED
data/roku_builder.gemspec
CHANGED
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
-
spec.required_ruby_version = "~> 2.2"
|
21
|
+
spec.required_ruby_version = "~> 2.2.3"
|
22
22
|
|
23
23
|
spec.add_dependency "rubyzip", "~> 1.2"
|
24
24
|
spec.add_dependency "faraday", "~> 0.9"
|
@@ -11,7 +11,7 @@ class ControllerCommandsTest < Minitest::Test
|
|
11
11
|
config = good_config
|
12
12
|
code, configs = RokuBuilder::ConfigParser.parse_config(options: options, config: config, logger: logger)
|
13
13
|
# Test Success
|
14
|
-
loader.expect(:sideload,
|
14
|
+
loader.expect(:sideload, [RokuBuilder::SUCCESS, "build_version"], [configs[:sideload_config]])
|
15
15
|
stager.expect(:stage, true)
|
16
16
|
stager.expect(:unstage, true)
|
17
17
|
stager.expect(:method, :git)
|
@@ -27,7 +27,7 @@ class ControllerCommandsTest < Minitest::Test
|
|
27
27
|
stager.expect(:unstage, true)
|
28
28
|
|
29
29
|
# Test Failure
|
30
|
-
loader.expect(:sideload,
|
30
|
+
loader.expect(:sideload, [RokuBuilder::FAILED_SIDELOAD, "build_version"], [configs[:sideload_config]])
|
31
31
|
RokuBuilder::Loader.stub(:new, loader) do
|
32
32
|
RokuBuilder::Stager.stub(:new, stager) do
|
33
33
|
code = RokuBuilder::Controller.send(:execute_commands, {options: options, config: config, configs: configs, logger: logger})
|
@@ -52,7 +52,7 @@ class ControllerCommandsTest < Minitest::Test
|
|
52
52
|
code, configs = RokuBuilder::ConfigParser.parse_config(options: options, config: config, logger: logger)
|
53
53
|
info = {app_name: "app", dev_id: "id", creation_date: "date", dev_zip: ""}
|
54
54
|
|
55
|
-
loader.expect(:sideload, "build_version", [configs[:sideload_config]])
|
55
|
+
loader.expect(:sideload, [RokuBuilder::SUCCESS, "build_version"], [configs[:sideload_config]])
|
56
56
|
keyer.expect(:rekey, true, [configs[:key]])
|
57
57
|
packager.expect(:package, true, [configs[:package_config]])
|
58
58
|
inspector.expect(:inspect, info, [configs[:inspect_config]])
|
@@ -94,7 +94,7 @@ class ControllerCommandsTest < Minitest::Test
|
|
94
94
|
code, configs = RokuBuilder::ConfigParser.parse_config(options: options, config: config, logger: logger)
|
95
95
|
info = {app_name: "app", dev_id: "id", creation_date: "date", dev_zip: ""}
|
96
96
|
|
97
|
-
loader.expect(:sideload, "build_version", [configs[:sideload_config]])
|
97
|
+
loader.expect(:sideload, [RokuBuilder::SUCCESS, "build_version"], [configs[:sideload_config]])
|
98
98
|
keyer.expect(:rekey, true, [configs[:key]])
|
99
99
|
packager.expect(:package, true, [configs[:package_config]])
|
100
100
|
inspector.expect(:inspect, info, [configs[:inspect_config]])
|
@@ -36,7 +36,6 @@ class ControllerTest < Minitest::Test
|
|
36
36
|
assert_equal RokuBuilder::DEPRICATED, RokuBuilder::Controller.send(:validate_options, {options: options})
|
37
37
|
options = {
|
38
38
|
sideload: true,
|
39
|
-
in: "",
|
40
39
|
current: true
|
41
40
|
}
|
42
41
|
assert_equal RokuBuilder::VALID, RokuBuilder::Controller.send(:validate_options, {options: options})
|
@@ -45,7 +44,7 @@ class ControllerTest < Minitest::Test
|
|
45
44
|
in: "",
|
46
45
|
set_stage: true
|
47
46
|
}
|
48
|
-
assert_equal RokuBuilder::
|
47
|
+
assert_equal RokuBuilder::EXTRA_SOURCES, RokuBuilder::Controller.send(:validate_options, {options: options})
|
49
48
|
end
|
50
49
|
def test_controller_configure
|
51
50
|
logger = Logger.new("/dev/null")
|
@@ -17,8 +17,10 @@ class LoaderTest < Minitest::Test
|
|
17
17
|
init_params: {root_dir: root_dir}
|
18
18
|
}
|
19
19
|
loader_config = {
|
20
|
-
|
21
|
-
|
20
|
+
content: {
|
21
|
+
folders: ["source"],
|
22
|
+
files: ["manifest"]
|
23
|
+
}
|
22
24
|
}
|
23
25
|
payload = {
|
24
26
|
mysubmit: "Replace",
|
@@ -38,22 +40,26 @@ class LoaderTest < Minitest::Test
|
|
38
40
|
end
|
39
41
|
response.expect(:status, 200)
|
40
42
|
response.expect(:body, "Install Success")
|
43
|
+
response.expect(:status, 200)
|
44
|
+
response.expect(:body, "Install Success")
|
41
45
|
|
42
46
|
loader = RokuBuilder::Loader.new(**device_config)
|
43
47
|
result = nil
|
48
|
+
build_version = nil
|
44
49
|
RokuBuilder::ManifestManager.stub(:build_version, "build_version") do
|
45
50
|
loader.stub(:build, "zip_file") do
|
46
51
|
Faraday.stub(:new, connection, faraday) do
|
47
52
|
Faraday::UploadIO.stub(:new, io) do
|
48
53
|
File.stub(:delete, nil) do
|
49
|
-
result = loader.sideload(**loader_config)
|
54
|
+
result, build_version = loader.sideload(**loader_config)
|
50
55
|
end
|
51
56
|
end
|
52
57
|
end
|
53
58
|
end
|
54
59
|
end
|
55
60
|
|
56
|
-
assert_equal "build_version",
|
61
|
+
assert_equal "build_version", build_version
|
62
|
+
assert_equal RokuBuilder::SUCCESS, result
|
57
63
|
|
58
64
|
connection.verify
|
59
65
|
faraday.verify
|
@@ -77,8 +83,10 @@ class LoaderTest < Minitest::Test
|
|
77
83
|
}
|
78
84
|
loader_config = {
|
79
85
|
update_manifest: true,
|
80
|
-
|
81
|
-
|
86
|
+
content: {
|
87
|
+
folders: ["source"],
|
88
|
+
files: ["manifest"]
|
89
|
+
}
|
82
90
|
}
|
83
91
|
payload = {
|
84
92
|
mysubmit: "Replace",
|
@@ -98,22 +106,26 @@ class LoaderTest < Minitest::Test
|
|
98
106
|
end
|
99
107
|
response.expect(:status, 200)
|
100
108
|
response.expect(:body, "Install Success")
|
109
|
+
response.expect(:status, 200)
|
110
|
+
response.expect(:body, "Install Success")
|
101
111
|
|
102
112
|
loader = RokuBuilder::Loader.new(**device_config)
|
103
113
|
result = nil
|
114
|
+
build_version = nil
|
104
115
|
RokuBuilder::ManifestManager.stub(:update_build, "build_version") do
|
105
116
|
loader.stub(:build, "zip_file") do
|
106
117
|
Faraday.stub(:new, connection, faraday) do
|
107
118
|
Faraday::UploadIO.stub(:new, io) do
|
108
119
|
File.stub(:delete, nil) do
|
109
|
-
result = loader.sideload(**loader_config)
|
120
|
+
result, build_version = loader.sideload(**loader_config)
|
110
121
|
end
|
111
122
|
end
|
112
123
|
end
|
113
124
|
end
|
114
125
|
end
|
115
126
|
|
116
|
-
assert_equal "build_version",
|
127
|
+
assert_equal "build_version", build_version
|
128
|
+
assert_equal RokuBuilder::SUCCESS, result
|
117
129
|
|
118
130
|
connection.verify
|
119
131
|
faraday.verify
|
@@ -132,8 +144,10 @@ class LoaderTest < Minitest::Test
|
|
132
144
|
init_params: {root_dir: root_dir}
|
133
145
|
}
|
134
146
|
build_config = {
|
135
|
-
|
136
|
-
|
147
|
+
content: {
|
148
|
+
folders: ["source"],
|
149
|
+
files: ["manifest"]
|
150
|
+
}
|
137
151
|
}
|
138
152
|
loader = RokuBuilder::Loader.new(**device_config)
|
139
153
|
outfile = nil
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: roku_builder
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- greeneca
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-05-
|
11
|
+
date: 2016-05-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rubyzip
|
@@ -317,7 +317,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
317
317
|
requirements:
|
318
318
|
- - "~>"
|
319
319
|
- !ruby/object:Gem::Version
|
320
|
-
version:
|
320
|
+
version: 2.2.3
|
321
321
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
322
322
|
requirements:
|
323
323
|
- - ">="
|