roku_builder 4.28.0 → 4.29.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 46e81906787a2404d186ec7a628e03c41a9b918c0f9af442c3bfd49e765df12b
4
- data.tar.gz: befa6a6ba8d8f4ccac02080ac26644b010366cfbeefe3e13e278abadff48a75c
3
+ metadata.gz: f65c1d45145a53ba384191e6ca28de7698ce3f38300133293ae9d1639945ee8f
4
+ data.tar.gz: 556b118faaa21814e4c8bf7c3d68c94a1a6360e029ce3bc2351d1f7a24fb5563
5
5
  SHA512:
6
- metadata.gz: 2d332bb657dcbb40691b521e8c65f8dca2357ad7fb53e94af334c1e5c9e8acabe4e0dc4eaa5f3bc40fd13e1190d2a2ac201dd9cb61c6258baf8bbbb88592f9a1
7
- data.tar.gz: d0ab2b92f24d46a305ee943635e75e2513240679db8316b71591b3dc97e525689155e79acf7fe8560fdd2777b0887330f0f4f4c94ecb379bafa2ccfcf060daa4
6
+ metadata.gz: ab7e70ba97918b750a18ea9774ad2bb871d0e5162d1f006d8ab7a20f2981fe212ac48bc89a66bac2a666ee744c73720e7b51c52f2f3136ff6e72193d6e880313
7
+ data.tar.gz: ddb429ba2119e3a26e8bc775dbd7092c8d37f0d6ee38567f5fe2875cae2a1a12a32d4c8a5cae5b79cb678fe8c908f5422d15cab5b9cd14aa96804ac519ffbfc3
@@ -127,7 +127,6 @@ module RokuBuilder
127
127
  if File.exist?(local_config_path) and !@loaded_configs.include?(File.expand_path(local_config_path))
128
128
  local_config_hash = read_config(File.open(local_config_path))
129
129
  add_missing_directories(local_config_hash)
130
- local_sub_configs = "./.roku_config/*.json"
131
130
  @config = @config.deep_merge(local_config_hash)
132
131
  Dir.glob("./.roku_config/*.json").each do |sub_config_path|
133
132
  sub_config_hash = read_config(File.open(sub_config_path))
@@ -22,6 +22,7 @@ module RokuBuilder
22
22
  def parse_config
23
23
  process_in_argument
24
24
  setup_devices
25
+ setup_api_keys
25
26
  setup_project
26
27
  setup_in_out_file
27
28
  setup_project_config
@@ -41,6 +42,10 @@ module RokuBuilder
41
42
  @parsed[:devices] = @config[:devices].select{|key, value| :default != key}
42
43
  end
43
44
 
45
+ def setup_api_keys
46
+ @parsed[:api_keys] = @config[:api_keys]
47
+ end
48
+
44
49
  def setup_project
45
50
  if project_required and not @options[:project]
46
51
  project = current_project
@@ -26,7 +26,7 @@ module RokuBuilder
26
26
  KEY_MISSING_PATH = 19
27
27
  KEY_MISSING_PASSWORD = 20
28
28
  INVALID_MAPPING_INFO = 21
29
- # = 22
29
+ INVALID_API_KEY = 22
30
30
  MISSING_STAGE_METHOD = 23
31
31
 
32
32
  def initialize(config:)
@@ -63,7 +63,7 @@ module RokuBuilder
63
63
  def validate_config
64
64
  @codes = []
65
65
  validate_structure
66
- [:projects, :devices, :keys, :input_mappings].each do |section|
66
+ [:projects, :devices, :keys, :input_mappings, :api_keys].each do |section|
67
67
  validate_section(section: section) if @config[section]
68
68
  end
69
69
  @codes.uniq!
@@ -174,6 +174,13 @@ module RokuBuilder
174
174
  process_errors(errors: errors)
175
175
  end
176
176
 
177
+ def validate_api_key(api_key:)
178
+ errors = [
179
+ [INVALID_API_KEY, (api_key.class != String)]
180
+ ]
181
+ process_errors(errors: errors)
182
+ end
183
+
177
184
  def process_errors(errors:)
178
185
  errors.each do |error|
179
186
  @codes.push(error[0]) if error[1]
@@ -115,7 +115,7 @@ module RokuBuilder
115
115
  multipart_connection(device: device) do |conn|
116
116
  response = conn.post "/plugin_install", payload
117
117
  end
118
- unless response.status == 200 and response.body =~ /squashfs file in internal memory/ or ignoreFailure
118
+ unless response.status == 200 and response.body =~ /Conversion succeeded/ or ignoreFailure
119
119
  raise ExecutionError, "Failed Converting to Squashfs"
120
120
  end
121
121
  end
@@ -135,7 +135,7 @@ module RokuBuilder
135
135
  # @param txt [String] current string from telnet
136
136
  # @param regexp [Regexp] regular expression to filter text on
137
137
  # @return [String] remaining partial line text
138
- def manage_text(all_text:, txt:, regexp: nil, logging: false, logfile:)
138
+ def manage_text(all_text:, txt:, regexp: nil, logging: false, logfile: nil)
139
139
  raise ExecutionError, "Connection Closed" unless txt
140
140
  if /connection is already in use/ =~ txt
141
141
  raise ExecutionError, "Connection is in use"
@@ -82,7 +82,7 @@ module RokuBuilder
82
82
  get_device(device: device) do |device|
83
83
  oldId = dev_id(device: device)
84
84
 
85
- raise ExecutionError, "Missing Key Config" unless @config.key
85
+ raise ExecutionError, "No Key Found For Stage #{options[:stage]}" unless @config.key
86
86
 
87
87
  # upload new key with password
88
88
  payload = {
@@ -0,0 +1,181 @@
1
+ # ********** Copyright Viacom, Inc. Apache 2.0 **********
2
+
3
+ module RokuBuilder
4
+
5
+ # Load/Unload/Build roku applications
6
+ class RokuAPI < Util
7
+ extend Plugin
8
+
9
+ HOST = "https://apipub.roku.com"
10
+
11
+ def init
12
+ end
13
+
14
+ def self.commands
15
+ {
16
+ submit: {source: false},
17
+ publish: {}
18
+ }
19
+ end
20
+
21
+ def self.parse_options(parser:, options:)
22
+ parser.separator "Commands:"
23
+ parser.on("--submit", 'Submit a package to the Roku Portal') do
24
+ options[:submit] = true
25
+ end
26
+ parser.on("--publish", 'Publish an app on the Roku Portal') do
27
+ options[:publish] = true
28
+ end
29
+ parser.separator "Options:"
30
+ parser.on("--channel-id ID", 'ID of the channel to submit to/publish') do |id|
31
+ options[:channel_id] = id
32
+ end
33
+ parser.on("--api-key KEY", 'The API key to use to submit/publish') do |key|
34
+ options[:api_key] = key
35
+ end
36
+ parser.on("--no-publish", 'Prevent the channel from being automatically published when submitted') do
37
+ options[:no_publish] = true
38
+ end
39
+ end
40
+
41
+ def self.dependencies
42
+ []
43
+ end
44
+
45
+ def submit(options:)
46
+ raise RokuBuilder::InvalidOptions, "Missing channel id" unless options[:channel_id]
47
+ @logger.info "Submit to channel #{options[:channel_id]}"
48
+ @api_key = options[:api_key]
49
+ @no_publish = !!options[:no_publish]
50
+ response = get_channel_versions(options[:channel_id])
51
+ if response.first["channelState"] == "Unpublished"
52
+ response = update_channel_version(options[:channel_id], get_package(options), response.last["id"])
53
+ else
54
+ response = create_channel_version(options[:channel_id], get_package(options))
55
+ end
56
+ raise RokuBuilder::ExecutionError, "Request failed: #{response.reason_phrase}" unless response.success?
57
+ JSON.parse(response.body)
58
+ end
59
+
60
+ def publish(options:)
61
+ raise RokuBuilder::InvalidOptions, "Missing channel id" unless options[:channel_id]
62
+ @logger.info "Publish to channel #{options[:channel_id]}"
63
+ @api_key = options[:api_key]
64
+ response = get_channel_versions(options[:channel_id])
65
+ raise RokuBuilder::ExecutionError unless response.first["channelState"] == "Unpublished"
66
+ response = publish_channel_version(options[:channel_id], response.first["id"])
67
+ raise RokuBuilder::ExecutionError, "Request failed: #{response.reason_phrase}" unless response.success?
68
+ JSON.parse(response.body)
69
+ end
70
+
71
+ private
72
+
73
+ def get_package(options)
74
+ File.open(options[:in])
75
+ end
76
+
77
+ def api_path
78
+ "/developer/v1"
79
+ end
80
+
81
+ def get_channel_versions(channel)
82
+ path = "/external/channels/#{channel}/versions"
83
+ response = api_get(path)
84
+ sorted_versions(JSON.parse(response.body))
85
+ end
86
+
87
+ def sorted_versions(versions)
88
+ sorted = versions.sort do |a, b|
89
+ DateTime.parse(b["createdDate"]) <=> DateTime.parse(a["createdDate"])
90
+ end
91
+ sorted
92
+ end
93
+
94
+ def create_channel_version(channel, package)
95
+ path = "/external/channels/#{channel}/versions"
96
+ params = nil
97
+ unless @no_publish
98
+ params = {"channelState" => "Published"}
99
+ end
100
+ api_post(path, path, package, params)
101
+ end
102
+
103
+ def update_channel_version(channel, package, version)
104
+ path = "/external/channel/#{channel}/#{version}"
105
+ token_path = "/external/channels/#{channel}/#{version}"
106
+ api_patch(path, token_path, package)
107
+ end
108
+
109
+ def publish_channel_version(channel, version)
110
+ path = "/external/channels/#{channel}/versions/#{version}"
111
+ token_path = "/external/channels/#{channel}/versions/#{version}/state"
112
+ api_post(path, token_path)
113
+ end
114
+
115
+ def api_get(path)
116
+ service_urn = "urn:roku:cloud-services:chanprovsvc"
117
+ connection('GET', path, nil).get(api_path+path)
118
+ end
119
+
120
+ def api_post(path, token_path, package=nil, params = nil)
121
+ body = {}.to_json
122
+ if package
123
+ body = {
124
+ "appFileBase64Encoded" => Base64.encode64(package.read)
125
+ }.to_json
126
+ end
127
+ connection('POST', token_path, body).post(api_path+path) do |request|
128
+ if params
129
+ request.params = params
130
+ end if
131
+ request.body = body
132
+ end
133
+ end
134
+
135
+ def api_patch(path, token_path, package)
136
+ body = {
137
+ "path" => "/appFileBase64Encoded",
138
+ "value" => Base64.encode64(package.read),
139
+ "op" => "replace"
140
+ }.to_json
141
+ response = connection('PATCH', token_path, body).patch(api_path+path) do |request|
142
+ request.body = body
143
+ end
144
+ end
145
+
146
+ def connection(method, path, body)
147
+ service_urn = "urn:roku:cloud-services:chanprovsvc"
148
+ connection = Faraday.new(url: HOST, headers: {
149
+ 'Authorization' => "Bearer "+get_jwt_token(@api_key, service_urn, method, path, body),
150
+ 'Content-Type' => 'application/json',
151
+ 'Accept' => 'application/json',
152
+ }) do |f|
153
+ f.adapter Faraday.default_adapter
154
+ end
155
+ end
156
+
157
+ def get_jwt_token(api_key, service_urn, method, path, body = nil)
158
+ key_file = File.expand_path(@config.api_keys[api_key.to_sym])
159
+ raise InvalidOptions "Missing api key" unless key_file
160
+ jwk = JWT::JWK.new(JSON.parse(File.read(key_file)))
161
+ header = {
162
+ "typ" => "JWT",
163
+ "kid" => jwk.export[:kid]
164
+ }
165
+ payload = {
166
+ "exp" => (Time.now + (12*60*60)).to_i,
167
+ "x-roku-request-key" => SecureRandom.uuid,
168
+ "x-roku-request-spec" => {
169
+ "serviceUrn" => service_urn,
170
+ "httpMethod" => method,
171
+ "path" => path,
172
+ }
173
+ }
174
+ if body
175
+ payload["x-roku-request-spec"]["bodySha256Base64"] = Digest::SHA256.base64digest(body)
176
+ end
177
+ JWT.encode(payload, jwk.signing_key, 'RS256', header)
178
+ end
179
+ end
180
+ RokuBuilder.register_plugin(RokuAPI)
181
+ end
@@ -2,5 +2,5 @@
2
2
 
3
3
  module RokuBuilder
4
4
  # Version of the RokuBuilder Gem
5
- VERSION = "4.28.0"
5
+ VERSION = "4.29.2"
6
6
  end
data/lib/roku_builder.rb CHANGED
@@ -27,6 +27,9 @@ require "tmpdir"
27
27
  require "zip"
28
28
  #analyzer
29
29
  require "image_size"
30
+ #rokuapi
31
+ require "jwt"
32
+ require "base64"
30
33
 
31
34
 
32
35
  Dir.glob(File.join(File.dirname(__FILE__), "roku_builder", "*.rb")).each do |path|
data/roku_builder.gemspec CHANGED
@@ -30,6 +30,7 @@ Gem::Specification.new do |spec|
30
30
  spec.add_dependency "nokogiri", "~> 1.12"
31
31
  spec.add_dependency "win32-security", "~> 0.5" # For windows compatibility
32
32
  spec.add_dependency "image_size", "~> 2.0"
33
+ spec.add_dependency "jwt", "~> 2.7"
33
34
 
34
35
  spec.add_development_dependency "bundler", "~> 2.0"
35
36
  spec.add_development_dependency "rake", "~> 12.0"
@@ -153,11 +153,10 @@ module RokuBuilder
153
153
  logger.expect(severity, nil, [String])
154
154
 
155
155
  ::Logger.stub :new, logger do
156
- warnings = test_file(text: text, quiet: false)
156
+ test_file(text: text, quiet: false)
157
157
  end
158
158
 
159
159
  logger.verify
160
- warnings
161
160
  end
162
161
 
163
162
  def test(quiet=true)
@@ -120,8 +120,6 @@ module RokuBuilder
120
120
  assert help_text
121
121
  end
122
122
  def test_core_get_plugin_by_name
123
- parser = OptionParser.new
124
- options = {}
125
123
  plugin_name = Core.get_plugin_by_name("core")
126
124
  refute_nil plugin_name
127
125
  assert_match "RokuBuilder::Core", plugin_name.to_s
@@ -136,7 +136,7 @@ module RokuBuilder
136
136
  end
137
137
  def test_loader_squash
138
138
  @request_stubs.push(stub_request(:post, "http://#{@device_config[:ip]}/plugin_install").
139
- to_return(status: 200, body: "squashfs file in internal memory", headers: {}))
139
+ to_return(status: 200, body: "Conversion succeeded", headers: {}))
140
140
  @device_manager.expect(:reserve_device, @device, no_lock: false)
141
141
  @device_manager.expect(:release_device, nil, [@device])
142
142
 
@@ -0,0 +1,566 @@
1
+ # ********** Copyright Viacom, Inc. Apache 2.0 **********
2
+
3
+ require_relative "../test_helper.rb"
4
+
5
+ module RokuBuilder
6
+ class RokuAPITest < Minitest::Test
7
+ def setup
8
+ Logger.set_testing
9
+ RokuBuilder.class_variable_set(:@@dev, false)
10
+ RokuBuilder.setup_plugins
11
+ register_plugins(RokuAPI)
12
+ @config, @options = build_config_options_objects(RokuAPITest, {submit: true, channel_id: "1234", api_key: "key1"}, false)
13
+ @requests = []
14
+ end
15
+
16
+ def teardown
17
+ @requests.each {|req| remove_request_stub(req)}
18
+ WebMock.reset!
19
+ end
20
+
21
+ def test_commands
22
+ commands = RokuAPI.commands
23
+ refute_nil commands[:submit]
24
+ refute_nil commands[:publish]
25
+ end
26
+
27
+ def test_parse_options
28
+ parser = OptionParser.new
29
+ options = {}
30
+ RokuAPI.parse_options(parser: parser, options: options)
31
+ argv = ["roku", "--submit", "--publish", "--channel-id", "1234", "--api-key", "key1", "--no-publish"]
32
+ parser.parse! argv
33
+ assert options[:submit]
34
+ assert options[:publish]
35
+ assert_equal options[:channel_id], "1234"
36
+ assert_equal options[:api_key], "key1"
37
+ assert options[:no_publish]
38
+ end
39
+
40
+ def test_dependencies
41
+ assert_kind_of Array, RokuAPI.dependencies
42
+ assert_equal RokuAPI.dependencies.count, 0
43
+ end
44
+
45
+ def test_get_package
46
+ api = RokuAPI.new(config: @config)
47
+ options = {in: "in/path"}
48
+ called = false
49
+ open_proc = proc do |path|
50
+ called = true
51
+ assert_equal options[:in], path
52
+ end
53
+ File.stub(:open, open_proc) do
54
+ api.send(:get_package, options)
55
+ end
56
+ assert called
57
+ end
58
+
59
+ def test_api_path
60
+ api = RokuAPI.new(config: @config)
61
+ assert_equal "/developer/v1", api.send(:api_path)
62
+ end
63
+
64
+ def test_sorted_versions
65
+ api = RokuAPI.new(config: @config)
66
+ versions = [
67
+ {"version" => "1.9", "createdDate" => (DateTime.now - 30).to_s},
68
+ {"version" => "1.11", "createdDate" => (DateTime.now - 20).to_s},
69
+ {"version" => "2.3", "createdDate" => (DateTime.now - 10).to_s},
70
+ {"version" => "2.4", "createdDate" => (DateTime.now).to_s}
71
+ ]
72
+ sorted = api.send(:sorted_versions, versions)
73
+ assert_equal "2.4", sorted[0]["version"]
74
+ assert_equal "2.3", sorted[1]["version"]
75
+ assert_equal "1.11", sorted[2]["version"]
76
+ assert_equal "1.9", sorted[3]["version"]
77
+ versions = [
78
+ {"version" => "1.4", "createdDate" => (DateTime.now).to_s},
79
+ {"version" => "1.3", "createdDate" => (DateTime.now - 10).to_s}
80
+ ]
81
+ sorted = api.send(:sorted_versions, versions)
82
+ assert_equal "1.4", sorted[0]["version"]
83
+ assert_equal "1.3", sorted[1]["version"]
84
+ end
85
+
86
+ def test_get_jwt_token
87
+ api = RokuAPI.new(config: @config)
88
+ urn = "test:urn"
89
+ method = "GET"
90
+ path = "/test/path"
91
+ token = api.send(:get_jwt_token, @options[:api_key], urn, method, path)
92
+ jwk = JWT::JWK.new(JSON.parse(File.read(@config.api_keys[:key1])))
93
+ decoded = JWT.decode(token, jwk.public_key, true, {algorithm: 'RS256'})
94
+ assert_equal decoded[1]["typ"], "JWT"
95
+ assert_equal decoded[1]["alg"], "RS256"
96
+ assert_equal decoded[1]["kid"], jwk.export[:kid]
97
+
98
+ assert is_uuid?(decoded[0]["x-roku-request-key"])
99
+ spec = decoded[0]["x-roku-request-spec"]
100
+ refute_nil spec
101
+ assert_equal spec["serviceUrn"], urn
102
+ assert_equal spec["httpMethod"], method
103
+ assert_equal spec["path"], path
104
+ end
105
+
106
+ def test_get_jwt_token_with_body
107
+ api = RokuAPI.new(config: @config)
108
+ urn = "test:urn"
109
+ method = "GET"
110
+ path = "/test/path"
111
+ body = {
112
+ "appFileBase64Encoded" => Base64.encode64(File.open(File.join(test_files_path(RokuAPITest), "test.pkg")).read)
113
+ }
114
+ sha256 = Digest::SHA256.base64digest(body.to_json)
115
+ token = api.send(:get_jwt_token, @options[:api_key], urn, method, path, body.to_json)
116
+ jwk = JWT::JWK.new(JSON.parse(File.read(@config.api_keys[:key1])))
117
+ decoded = JWT.decode(token, jwk.public_key, true, {algorithm: 'RS256'})
118
+ assert_equal decoded[1]["typ"], "JWT"
119
+ assert_equal decoded[1]["alg"], "RS256"
120
+ assert_equal decoded[1]["kid"], jwk.export[:kid]
121
+
122
+ assert is_uuid?(decoded[0]["x-roku-request-key"])
123
+ spec = decoded[0]["x-roku-request-spec"]
124
+ refute_nil spec
125
+ assert_equal spec["serviceUrn"], urn
126
+ assert_equal spec["httpMethod"], method
127
+ assert_equal spec["path"], path
128
+ assert_equal spec["bodySha256Base64"], sha256
129
+ end
130
+
131
+ def test_api_get
132
+ api = RokuAPI.new(config: @config)
133
+ path = "/test/path"
134
+ api.instance_variable_set(:@api_key, "key1")
135
+ @requests.push(stub_request(:any, /apipub.roku.com.*/))
136
+ response = api.send(:api_get, path)
137
+ assert_requested(:get, "https://apipub.roku.com/developer/v1/test/path", headers: {
138
+ "Accept" => "application/json",
139
+ "Content-Type" => "application/json",
140
+ "Authorization" => /Bearer .*/
141
+ })
142
+ end
143
+
144
+ def test_api_post
145
+ api = RokuAPI.new(config: @config)
146
+ path = "/test/path"
147
+ token_path = "/other/path"
148
+ api.instance_variable_set(:@api_key, "key1")
149
+ package = File.open(File.join(test_files_path(RokuAPITest), "test.pkg"))
150
+ encoded = Base64.encode64(package.read)
151
+ @requests.push(stub_request(:any, /apipub.roku.com.*/))
152
+ called = false
153
+ jwt_proc = proc do |api_key, service_urn, method, path, body|
154
+ called = true
155
+ assert_equal path, token_path
156
+ "token"
157
+ end
158
+ params = {"status" => "Published"}
159
+ api.stub(:get_jwt_token, jwt_proc) do
160
+ response = api.send(:api_post, path, token_path, package, params)
161
+ end
162
+ assert called
163
+ assert_requested(:post, "https://apipub.roku.com/developer/v1/test/path",
164
+ body: {"appFileBase64Encoded" => encoded}.to_json,
165
+ headers: {
166
+ "Accept" => "application/json",
167
+ "Content-Type" => "application/json",
168
+ "Authorization" => /Bearer token/
169
+ },
170
+ query: {"status" => "Published"}
171
+ )
172
+ end
173
+
174
+ def test_api_post_no_package
175
+ api = RokuAPI.new(config: @config)
176
+ path = "/test/path"
177
+ token_path = "/other/path"
178
+ api.instance_variable_set(:@api_key, "key1")
179
+ @requests.push(stub_request(:any, /apipub.roku.com.*/))
180
+ called = false
181
+ jwt_proc = proc do |api_key, service_urn, method, path, body|
182
+ called = true
183
+ assert_equal path, token_path
184
+ "token"
185
+ end
186
+ api.stub(:get_jwt_token, jwt_proc) do
187
+ response = api.send(:api_post, path, token_path)
188
+ end
189
+ assert called
190
+ assert_requested(:post, "https://apipub.roku.com/developer/v1/test/path",
191
+ headers: {
192
+ "Accept" => "application/json",
193
+ "Content-Type" => "application/json",
194
+ "Authorization" => /Bearer .*/
195
+ }
196
+ )
197
+ end
198
+
199
+ def test_api_patch
200
+ api = RokuAPI.new(config: @config)
201
+ path = "/test/path"
202
+ token_path = "/other/path"
203
+ api.instance_variable_set(:@api_key, "key1")
204
+ package = File.open(File.join(test_files_path(RokuAPITest), "test.pkg"))
205
+ encoded = Base64.encode64(package.read)
206
+ @requests.push(stub_request(:any, /apipub.roku.com.*/))
207
+ called = false
208
+ jwt_proc = proc do |api_key, service_urn, method, path, body|
209
+ called = true
210
+ assert_equal path, token_path
211
+ "token"
212
+ end
213
+ api.stub(:get_jwt_token, jwt_proc) do
214
+ response = api.send(:api_patch, path, token_path, package)
215
+ end
216
+ assert called
217
+ assert_requested(:patch, "https://apipub.roku.com/developer/v1/test/path",
218
+ body: {"path" => "/appFileBase64Encoded", "value" => encoded, "op" => "replace"}.to_json,
219
+ headers: {
220
+ "Accept" => "application/json",
221
+ "Content-Type" => "application/json",
222
+ "Authorization" => /Bearer token/
223
+ }
224
+ )
225
+ end
226
+
227
+ def test_get_channel_versions
228
+ api = RokuAPI.new(config: @config)
229
+ channel = "1234"
230
+ api.instance_variable_set(:@api_key, "key1")
231
+ response = Minitest::Mock.new
232
+ body = { "id" => "1234", "version" => "1.1"}
233
+ response.expect(:body, body.to_json)
234
+ called = 0
235
+ get_proc = proc do |path|
236
+ called +=1
237
+ assert_equal path, "/external/channels/#{channel}/versions"
238
+ response
239
+ end
240
+ sort_proc = proc do |versions|
241
+ called += 1
242
+ versions
243
+ end
244
+ api.stub(:api_get, get_proc) do
245
+ api.stub(:sorted_versions, sort_proc) do
246
+ result = api.send(:get_channel_versions, channel)
247
+ assert_equal result, body
248
+ end
249
+ end
250
+ assert_equal 2, called
251
+ end
252
+
253
+ def test_submit_no_channel_id
254
+ api = RokuAPI.new(config: @config)
255
+ assert_raises RokuBuilder::InvalidOptions do
256
+ api.submit(options: {})
257
+ end
258
+ end
259
+
260
+ def test_submit_without_unpublished
261
+ api = RokuAPI.new(config: @config)
262
+ called = {}
263
+ @options[:no_publish] = true
264
+ response = Minitest::Mock.new
265
+ response.expect(:success?, true)
266
+ response.expect(:body, api_versions[0].to_json)
267
+ updated = proc {called[:updated] = true; response}
268
+ created = proc {called[:created] = true; response}
269
+ @requests.push(stub_request(:any, "https://apipub.roku.com/developer/v1/external/channels/1234/versions").to_return(
270
+ body: api_versions.to_json
271
+ ))
272
+ api.stub(:create_channel_version, created) do
273
+ api.stub(:update_channel_version, updated) do
274
+ api.stub(:get_package, "") do
275
+ api.submit(options: @options)
276
+ end
277
+ end
278
+ end
279
+ assert called[:created]
280
+ assert_nil called[:updated]
281
+ assert api.instance_variable_get(:@no_publish)
282
+
283
+ end
284
+ def test_submit_without_latest_unpublished
285
+ api = RokuAPI.new(config: @config)
286
+ called = {}
287
+ body = api_versions
288
+ body.push(api_versions.first)
289
+ body[1]["version"] = "1.3"
290
+ body[1]["channelState"] = "Unpublished"
291
+ body[1]["createdDate"] = (DateTime.now -10).to_s
292
+ response = Minitest::Mock.new
293
+ response.expect(:success?, true)
294
+ response.expect(:body, body[0].to_json)
295
+ updated = proc {called[:updated] = true; response}
296
+ created = proc {called[:created] = true; response}
297
+ @requests.push(stub_request(:any, "https://apipub.roku.com/developer/v1/external/channels/1234/versions").to_return(
298
+ body: body.to_json
299
+ ))
300
+ api.stub(:create_channel_version, created) do
301
+ api.stub(:update_channel_version, updated) do
302
+ api.stub(:get_package, "") do
303
+ api.submit(options: @options)
304
+ end
305
+ end
306
+ end
307
+ assert called[:created]
308
+ assert_nil called[:updated]
309
+ end
310
+
311
+ def test_submit_with_unpublished
312
+ api = RokuAPI.new(config: @config)
313
+ body = api_versions
314
+ body[0]["channelState"] = "Unpublished"
315
+ called = {}
316
+ response = Minitest::Mock.new
317
+ response.expect(:success?, true)
318
+ response.expect(:body, body[0].to_json)
319
+ updated = proc do |channel, package, version|
320
+ called[:updated] = true
321
+ assert_equal body[0]["id"], version
322
+ response
323
+ end
324
+ created = proc {called[:created] = true; response}
325
+ @requests.push(stub_request(:any, "https://apipub.roku.com/developer/v1/external/channels/1234/versions").to_return(
326
+ body: body.to_json
327
+ ))
328
+ api.stub(:create_channel_version, created) do
329
+ api.stub(:update_channel_version, updated) do
330
+ api.stub(:get_package, "") do
331
+ api.submit(options: @options)
332
+ end
333
+ end
334
+ end
335
+ assert called[:updated]
336
+ assert_nil called[:created]
337
+ end
338
+
339
+ def test_create_channel_version
340
+ api = RokuAPI.new(config: @config)
341
+ channel = "1234"
342
+ api.instance_variable_set(:@api_key, "key1")
343
+ package = File.open(File.join(test_files_path(RokuAPITest), "test.pkg"))
344
+ called = false
345
+ post_proc = proc do |path, token_path, package, params|
346
+ called = true
347
+ assert_equal path, "/external/channels/#{channel}/versions"
348
+ assert_equal token_path, "/external/channels/#{channel}/versions"
349
+ assert_equal "Published", params["channelState"]
350
+ assert_kind_of File, package
351
+ end
352
+ api.stub(:api_post, post_proc) do
353
+ api.send(:create_channel_version, channel, package)
354
+ end
355
+ assert called
356
+ end
357
+
358
+ def test_create_channel_version_no_publish
359
+ api = RokuAPI.new(config: @config)
360
+ channel = "1234"
361
+ api.instance_variable_set(:@api_key, "key1")
362
+ api.instance_variable_set(:@no_publish, true)
363
+ package = File.open(File.join(test_files_path(RokuAPITest), "test.pkg"))
364
+ called = false
365
+ post_proc = proc do |path, token_path, package, params|
366
+ called = true
367
+ assert_equal path, "/external/channels/#{channel}/versions"
368
+ assert_equal token_path, "/external/channels/#{channel}/versions"
369
+ assert_nil params
370
+ assert_kind_of File, package
371
+ end
372
+ api.stub(:api_post, post_proc) do
373
+ api.send(:create_channel_version, channel, package)
374
+ end
375
+ assert called
376
+ end
377
+
378
+ def test_update_channel_version
379
+ api = RokuAPI.new(config: @config)
380
+ channel = "1234"
381
+ version = "1234"
382
+ api.instance_variable_set(:@api_key, "key1")
383
+ package = File.open(File.join(test_files_path(RokuAPITest), "test.pkg"))
384
+ called = false
385
+ patch_proc = proc do |path, token_path, package|
386
+ called = true
387
+ assert_equal path, "/external/channel/#{channel}/#{version}"
388
+ assert_equal token_path, "/external/channels/#{channel}/#{version}"
389
+ assert_kind_of File, package
390
+ end
391
+ api.stub(:api_patch, patch_proc) do
392
+ api.send(:update_channel_version, channel, package, version)
393
+ end
394
+ assert called
395
+ end
396
+
397
+ def test_publish_no_channel_id
398
+ api = RokuAPI.new(config: @config)
399
+ assert_raises RokuBuilder::InvalidOptions do
400
+ params = {options: {}}
401
+ api.send(:publish, **params)
402
+ end
403
+ end
404
+
405
+ def test_publish_without_unpublished
406
+ api = RokuAPI.new(config: @config)
407
+ expected_channel = "1234"
408
+ api.instance_variable_set(:@api_key, "key1")
409
+ body = api_versions
410
+ called = false
411
+ get_proc = proc do |channel|
412
+ called = true
413
+ assert_equal expected_channel, channel
414
+ body
415
+ end
416
+ api.stub(:get_channel_versions, get_proc) do
417
+ assert_raises RokuBuilder::ExecutionError do
418
+ params = {options: {channel_id: expected_channel}}
419
+ api.send(:publish, **params)
420
+ end
421
+ end
422
+ assert called
423
+ end
424
+
425
+ def test_publish_without_latest_unpublished
426
+ api = RokuAPI.new(config: @config)
427
+ expected_channel = "1234"
428
+ api.instance_variable_set(:@api_key, "key1")
429
+ body = api_versions
430
+ body.push(api_versions.first)
431
+ body[1]["version"] = "1.3"
432
+ body[1]["channelState"] = "Unpublished"
433
+ called = false
434
+ get_proc = proc do |channel|
435
+ called = true
436
+ assert_equal expected_channel, channel
437
+ body
438
+ end
439
+ api.stub(:get_channel_versions, get_proc) do
440
+ assert_raises RokuBuilder::ExecutionError do
441
+ params = {options: {channel_id: expected_channel}}
442
+ api.send(:publish, **params)
443
+ end
444
+ end
445
+ assert called
446
+ end
447
+
448
+ def test_publish_with_unpublished
449
+ api = RokuAPI.new(config: @config)
450
+ expected_channel = "1234"
451
+ api.instance_variable_set(:@api_key, "key1")
452
+ body = [{ "id" => "1234", "version" => "1.1", "channelState" => "Unpublished"}]
453
+ called = 0
454
+ get_proc = proc do |channel|
455
+ called += 1
456
+ assert_equal expected_channel, channel
457
+ body
458
+ end
459
+ response = Minitest::Mock.new
460
+ response.expect(:success?, true)
461
+ response.expect(:body, body[0].to_json)
462
+ post_proc = proc do |channel, version|
463
+ called += 1
464
+ assert_equal expected_channel, channel
465
+ assert_equal body.first["id"], version
466
+ response
467
+ end
468
+ api.stub(:get_channel_versions, get_proc) do
469
+ api.stub(:publish_channel_version, post_proc) do
470
+ params = {options: {channel_id: expected_channel}}
471
+ api.send(:publish, **params)
472
+ end
473
+ end
474
+ assert_equal called, 2
475
+ end
476
+
477
+ def test_publish_channel_version
478
+ api = RokuAPI.new(config: @config)
479
+ channel = "1234"
480
+ api.instance_variable_set(:@api_key, "key1")
481
+ response = Minitest::Mock.new
482
+ body = { "id" => "1234", "version" => "1.1"}
483
+ response.expect(:body, body.to_json)
484
+ called = false
485
+ post_proc = proc do |path, token_path|
486
+ called = true
487
+ assert_equal path, "/external/channels/#{channel}/versions/#{body["id"]}"
488
+ assert_equal token_path, "/external/channels/#{channel}/versions/#{body["id"]}/state"
489
+ end
490
+ api.stub(:api_post, post_proc) do
491
+ api.send(:publish_channel_version, channel, body["id"])
492
+ end
493
+ assert called
494
+ end
495
+
496
+ def test_submit_failure_create
497
+ api = RokuAPI.new(config: @config)
498
+ response = Minitest::Mock.new
499
+ response.expect(:success?, false)
500
+ response.expect(:reason_phrase, "reason")
501
+ api.stub(:get_channel_versions, api_versions) do
502
+ api.stub(:create_channel_version, response) do
503
+ api.stub(:get_package, "") do
504
+ assert_raises RokuBuilder::ExecutionError do
505
+ api.submit(options: @options)
506
+ end
507
+ end
508
+ end
509
+ end
510
+ assert_mock response
511
+ end
512
+
513
+ def test_submit_response_created
514
+ api = RokuAPI.new(config: @config)
515
+ body = { "id" => "1234", "version" => "1.1"}
516
+ response = Minitest::Mock.new
517
+ response.expect(:success?, true)
518
+ response.expect(:body, body.to_json)
519
+ api.stub(:get_channel_versions, api_versions) do
520
+ api.stub(:create_channel_version, response) do
521
+ api.stub(:get_package, "") do
522
+ response_json = api.submit(options: @options)
523
+ assert_equal body, response_json
524
+ end
525
+ end
526
+ end
527
+ assert_mock response
528
+ end
529
+
530
+ def test_submit_response_updated
531
+ api = RokuAPI.new(config: @config)
532
+ body = { "id" => "1234", "version" => "1.1"}
533
+ response = Minitest::Mock.new
534
+ response.expect(:success?, true)
535
+ response.expect(:body, body.to_json)
536
+ versions = api_versions
537
+ versions[0]["channelState"] = "Unpublished"
538
+ api.stub(:get_channel_versions, versions) do
539
+ api.stub(:update_channel_version, response) do
540
+ api.stub(:get_package, "") do
541
+ response_json = api.submit(options: @options)
542
+ assert_equal body, response_json
543
+ end
544
+ end
545
+ end
546
+ assert_mock response
547
+ end
548
+
549
+ def test_publish_response
550
+ api = RokuAPI.new(config: @config)
551
+ body = { "id" => "1234", "version" => "1.1"}
552
+ response = Minitest::Mock.new
553
+ response.expect(:success?, true)
554
+ response.expect(:body, body.to_json)
555
+ versions = api_versions
556
+ versions[0]["channelState"] = "Unpublished"
557
+ api.stub(:get_channel_versions, versions) do
558
+ api.stub(:publish_channel_version, response) do
559
+ response_json = api.publish(options: @options)
560
+ assert_equal body, response_json
561
+ end
562
+ end
563
+ assert_mock response
564
+ end
565
+ end
566
+ end
@@ -44,6 +44,22 @@ module RokuBuilder
44
44
  assert_equal File.join(Dir.pwd, "infile"), configs[:root_dir]
45
45
  end
46
46
 
47
+ def test_api_keys
48
+ options = build_options({
49
+ current: true,
50
+ validate: true
51
+ })
52
+ config = good_config(ConfigParserTest)
53
+ configs = nil
54
+ File.stub(:exist?, true) do
55
+ configs = ConfigParser.parse(options: options, config: config)
56
+ end
57
+
58
+ assert_kind_of Hash, configs
59
+ assert_kind_of Hash, configs[:api_keys]
60
+ assert_equal configs[:api_keys][:key1], File.join(test_files_path(ConfigParserTest), "test_key.json")
61
+ end
62
+
47
63
  def test_manifest_config_current
48
64
  options = build_options({
49
65
  current: true,
@@ -216,5 +216,19 @@ module RokuBuilder
216
216
  validator = ConfigValidator.new(config: config)
217
217
  assert_equal [12], validator.instance_variable_get(:@codes)
218
218
  end
219
+
220
+ def test_config_validate_invalid_api_key
221
+ config = good_config
222
+ config[:api_keys][:key1] = nil
223
+ validator = ConfigValidator.new(config: config)
224
+ assert_equal [22], validator.instance_variable_get(:@codes)
225
+ end
226
+
227
+ def test_confif_validate_no_api_keys
228
+ config = good_config
229
+ config[:api_keys] = nil
230
+ validator = ConfigValidator.new(config: config)
231
+ assert_equal [0], validator.instance_variable_get(:@codes)
232
+ end
219
233
  end
220
234
  end
@@ -39,7 +39,7 @@ module RokuBuilder
39
39
  @ping.expect(:ping?, false, [config.raw[:devices][:roku][:ip], 1, 0.2, 1])
40
40
  manager = DeviceManager.new(config: config, options: options)
41
41
  assert_raises(DeviceError) do
42
- device = manager.reserve_device
42
+ manager.reserve_device
43
43
  end
44
44
  end
45
45
  end
@@ -50,9 +50,9 @@ module RokuBuilder
50
50
  @ping.expect(:ping?, true, [config.raw[:devices][:roku][:ip], 1, 0.2, 1])
51
51
  @ping.expect(:ping?, true, [config.raw[:devices][:roku][:ip], 1, 0.2, 1])
52
52
  manager = DeviceManager.new(config: config, options: options)
53
- device1 = manager.reserve_device
53
+ manager.reserve_device
54
54
  assert_raises(DeviceError) do
55
- device2 = manager.reserve_device
55
+ manager.reserve_device
56
56
  end
57
57
  end
58
58
  end
@@ -121,7 +121,7 @@ module RokuBuilder
121
121
  manager = DeviceManager.new(config: config, options: options)
122
122
  device1 = manager.reserve_device
123
123
  assert_raises(DeviceError) do
124
- device2 = manager.reserve_device
124
+ manager.reserve_device
125
125
  end
126
126
  assert_equal "test2", device1.name
127
127
  end
@@ -0,0 +1,13 @@
1
+ {
2
+ "kty": "RSA",
3
+ "kid": "hbdk0JpkFRc39Dx7WXxKkntR0UeCp-J7PiWWkwGOaHk",
4
+ "alg": "RS256",
5
+ "e": "AQAB",
6
+ "n": "xRFv0nywIFBexub60g-bi4ZwEOj_E-bA_bqO99w6kbAMu_XqAvYaIu2StZK1SedrK-kKcOCXFfEbCGlM0CZnrIXU5usRERvS1dDUZz3KyJ9DPi4VMUgTTONM6m_NrfgOa8-V71LcNXcnQ2ZhWTvffcvgZ7Btz0yMbuwhIKlJNEs9MtrZDV_yWpbns-kQDH1A3PS22ZNGej7ifJJuIX1KitDLvkjrYR8MaCf-PUJewU-7ugpvO1pNi6ChYcTY09YuScPYiZg5i9yClve0lwScw2DBIBMfxyAG626YZtUkv6ffKQuceak-w0vx7gYLOJv_aCyKNcxrmFmMYwDIbXDaHQ",
7
+ "d": "G0wdBzUKWI-JcVfRaoOK8jq_DziXDLSsCvlqkF7LJh8SxH592ccpO6lY5xnZTtFlgQGY1qXlh76MFhAv-a04MyeepBXvmUUXYVK5-UsP6dZVxCkx-k-XjND3eIngHbb8mGZ6yFnb8vP8VlO6LFgkzxIMlZBUxaA-26aNuC5622lKUoQQiD3eVxu93hIOAjn08dMn4yl8D4MbD8kfkWeQIXM0VI25YjKlt2mJSajyMxxMFTIrevoGo72tEgjpER--EDXMBuq0KsPSU7ZHfLhs6Dk2bcG79JAZ4WG17gkoO1atjta_kPXik4MQEeQYFgT3kaLSsSvhv3ipp28nOwFugQ",
8
+ "p": "7OeIV6zOUlyWcNvX4uwRy_qKo-JAltmSqIiTQmry9l2HDFEV3hnPnV5uyYU6uIo-OWMTWxWR_41Wl45Na15DYhcY8ttudAseiPHPqczhbm5jCzYSt6vY4prKDMXP3rXbRb9wGPm22BqU-ERxQz_vwMhXxDhLaHjOZ3ihjcFI440",
9
+ "q": "1PPkKEGmegHkH7YPXoZyz90qk2FRBBY76ulU-ThXaaMDiS0vDJqcwrvpk9UDT3hdnZhh0zLhlS1C9ypvnQDqTA7p8h_my0VL9bXVcEgUzzkgQ_Vjyq9-6Lb2y9HGqXUoycLS4xss5qXZOM26oFGkeRgfGXZo2Ndlb-zGQN88ZNE",
10
+ "dp": "2Q1FGPclzcYwu9RglvMtVxMEpSRtgwhy22DOcwLj-h801W8RNv20_3z-yjn71Aos-o0wtbosmtRXKuJhQmcKG7wHyrKLH1z0rAnI9szVGkWfDy2KtqeHPg8N4ef3DRjXfq7oOKnKAXNRW6nxj-jrdFjaONhPFrfgfGLEuckGTB0",
11
+ "dq": "HWWZrnD5oUgXjMUeNAdNXCKE2RmLDIxhMxmI0GqVrpCBUXN6VjwVvdAg-3ZhYZwVGEdL4dLZTzWTU_l4tOzGaz93ziPXQWJMjRvP3hMlREH3kUoTv4wgcdGoGhTYXtY8jjWl1RIQTbrBVNUZmT4L_Wd2C5bL_Hsnlp7R82ydsrE",
12
+ "qi": "cnrYQq21HMSlYj3Ga_F8Su1H_9cKjZPJoeRcGagkBQpIx2zGxhheTEXZV7X9RFNyLev6zBXxue6PEhjAEEDqlNKNFXSmlLSkbDkKCMb1yeALTPSqrNFvq8DdH0cxMDTPI0U5K2JCwuAoAyXzWxENEiRlq4oizdzZBvilM7TF4fM"
13
+ }
@@ -71,56 +71,80 @@ def tmp_folder()
71
71
  Dir.tmpdir()
72
72
  end
73
73
 
74
+ def is_uuid?(uuid)
75
+ uuid_regex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/
76
+ return true if uuid_regex.match?(uuid.to_s.downcase)
77
+ false
78
+ end
79
+
74
80
  def good_config(klass=nil)
75
81
  root_dir = "/tmp"
76
82
  root_dir = test_files_path(klass) if klass
77
83
  {
78
84
  devices: {
79
- default: :roku,
80
- roku: {
81
- ip: "192.168.0.100",
82
- user: "user",
83
- password: "password"
84
- }
85
- },
85
+ default: :roku,
86
+ roku: {
87
+ ip: "192.168.0.100",
88
+ user: "user",
89
+ password: "password"
90
+ }
91
+ },
86
92
  projects: {
87
- default: :project1,
88
- project1: {
89
- directory: root_dir,
90
- source_files: ["manifest", "images", "source"],
91
- app_name: "<app name>",
92
- stage_method: :git,
93
- stages:{
94
- production: {
95
- branch: "production",
96
- key: {
97
- keyed_pkg: File.join(root_dir, "test.pkg"),
98
- password: "password"
99
- }
100
- }
101
- }
102
- },
103
- project2: {
104
- directory: root_dir,
105
- source_files: ["images","source","manifest"],
106
- app_name: "<app name>",
107
- stage_method: :script,
108
- stages:{
109
- production: {
110
- script: {stage: "stage_script", unstage: "unstage_script"},
111
- key: "a"
112
- }
113
- }
114
- }
115
- },
93
+ default: :project1,
94
+ project1: {
95
+ directory: root_dir,
96
+ source_files: ["manifest", "images", "source"],
97
+ app_name: "<app name>",
98
+ stage_method: :git,
99
+ stages:{
100
+ production: {
101
+ branch: "production",
102
+ key: {
103
+ keyed_pkg: File.join(root_dir, "test.pkg"),
104
+ password: "password"
105
+ }
106
+ }
107
+ }
108
+ },
109
+ project2: {
110
+ directory: root_dir,
111
+ source_files: ["images","source","manifest"],
112
+ app_name: "<app name>",
113
+ stage_method: :script,
114
+ stages:{
115
+ production: {
116
+ script: {stage: "stage_script", unstage: "unstage_script"},
117
+ key: "a"
118
+ }
119
+ }
120
+ }
121
+ },
116
122
  keys: {
117
- a: {
118
- keyed_pkg: File.join(root_dir, "test.pkg"),
119
- password: "password"
120
- }
121
- },
123
+ a: {
124
+ keyed_pkg: File.join(root_dir, "test.pkg"),
125
+ password: "password"
126
+ }
127
+ },
122
128
  input_mappings: {
123
- "a": ["home", "Home"]
124
- }
129
+ "a": ["home", "Home"]
130
+ },
131
+ api_keys: {
132
+ key1: File.join(root_dir, "test_key.json")
133
+ }
125
134
  }
126
135
  end
136
+
137
+ def api_versions
138
+ [
139
+ {
140
+ "id" => "5735B375-2607-435F-97AE-66954DC2A91F",
141
+ "channelState" => "Published",
142
+ "appSize" => 1226192,
143
+ "channelId" => 722085,
144
+ "version" => "1.4",
145
+ "minFirmwareVersion" => 0,
146
+ "minimumFirmwareVersionTextShort" => "v2.5 b388",
147
+ "createdDate" => DateTime.now.to_s
148
+ }
149
+ ]
150
+ end
@@ -10,12 +10,12 @@ class GitTest < Minitest::Test
10
10
 
11
11
  index = 1
12
12
  base.expect(:lib, lib)
13
+ base.expect(:lib, lib)
14
+ lib.expect(:stashes_all, [])
13
15
  lib.expect(:stash_pop, nil, [index])
14
16
 
15
17
  Dir.mktmpdir do |dir|
16
- git = Git.init(File.join(dir, "git"))
17
- stashes = git.branch.stashes
18
- stashes.instance_variable_set(:@base, base)
18
+ stashes = Git::Stashes.new(base)
19
19
  stashes.pop(index)
20
20
  end
21
21
 
@@ -29,12 +29,12 @@ class GitTest < Minitest::Test
29
29
 
30
30
  index = 1
31
31
  base.expect(:lib, lib)
32
+ base.expect(:lib, lib)
33
+ lib.expect(:stashes_all, [])
32
34
  lib.expect(:stash_drop, nil, [index])
33
35
 
34
36
  Dir.mktmpdir do |dir|
35
- git = Git.init(File.join(dir, "git"))
36
- stashes = git.branch.stashes
37
- stashes.instance_variable_set(:@base, base)
37
+ stashes = Git::Stashes.new(base)
38
38
  stashes.drop(index)
39
39
  end
40
40
 
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: 4.28.0
4
+ version: 4.29.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - greeneca
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-02-09 00:00:00.000000000 Z
11
+ date: 2024-01-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rubyzip
@@ -150,6 +150,20 @@ dependencies:
150
150
  - - "~>"
151
151
  - !ruby/object:Gem::Version
152
152
  version: '2.0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: jwt
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - "~>"
158
+ - !ruby/object:Gem::Version
159
+ version: '2.7'
160
+ type: :runtime
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - "~>"
165
+ - !ruby/object:Gem::Version
166
+ version: '2.7'
153
167
  - !ruby/object:Gem::Dependency
154
168
  name: bundler
155
169
  requirement: !ruby/object:Gem::Requirement
@@ -514,6 +528,7 @@ files:
514
528
  - lib/roku_builder/plugins/packager.rb
515
529
  - lib/roku_builder/plugins/performance_config.json
516
530
  - lib/roku_builder/plugins/profiler.rb
531
+ - lib/roku_builder/plugins/rokuapi.rb
517
532
  - lib/roku_builder/plugins/sca-cmd/LICENSE
518
533
  - lib/roku_builder/plugins/sca-cmd/README.md
519
534
  - lib/roku_builder/plugins/sca-cmd/bin/sca-cmd
@@ -536,6 +551,7 @@ files:
536
551
  - test/roku_builder/plugins/test_navigator.rb
537
552
  - test/roku_builder/plugins/test_packager.rb
538
553
  - test/roku_builder/plugins/test_profiler.rb
554
+ - test/roku_builder/plugins/test_rokuapi.rb
539
555
  - test/roku_builder/plugins/test_scripter.rb
540
556
  - test/roku_builder/plugins/test_tester.rb
541
557
  - test/roku_builder/test_config.rb
@@ -614,6 +630,8 @@ files:
614
630
  - test/roku_builder/test_files/packager_test/manifest
615
631
  - test/roku_builder/test_files/packager_test/scripter_test/manifest
616
632
  - test/roku_builder/test_files/packager_test/test.pkg
633
+ - test/roku_builder/test_files/roku_api_test/test.pkg
634
+ - test/roku_builder/test_files/roku_api_test/test_key.json
617
635
  - test/roku_builder/test_files/roku_builder_test/config.json
618
636
  - test/roku_builder/test_files/scripter_test/manifest
619
637
  - test/roku_builder/test_files/scripter_test/test.pkg
@@ -667,6 +685,7 @@ test_files:
667
685
  - test/roku_builder/plugins/test_navigator.rb
668
686
  - test/roku_builder/plugins/test_packager.rb
669
687
  - test/roku_builder/plugins/test_profiler.rb
688
+ - test/roku_builder/plugins/test_rokuapi.rb
670
689
  - test/roku_builder/plugins/test_scripter.rb
671
690
  - test/roku_builder/plugins/test_tester.rb
672
691
  - test/roku_builder/test_config.rb
@@ -745,6 +764,8 @@ test_files:
745
764
  - test/roku_builder/test_files/packager_test/manifest
746
765
  - test/roku_builder/test_files/packager_test/scripter_test/manifest
747
766
  - test/roku_builder/test_files/packager_test/test.pkg
767
+ - test/roku_builder/test_files/roku_api_test/test.pkg
768
+ - test/roku_builder/test_files/roku_api_test/test_key.json
748
769
  - test/roku_builder/test_files/roku_builder_test/config.json
749
770
  - test/roku_builder/test_files/scripter_test/manifest
750
771
  - test/roku_builder/test_files/scripter_test/test.pkg