fastlane-plugin-waldo 1.3.0 → 2.0.1
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 +5 -5
- data/README.md +43 -28
- data/lib/fastlane/plugin/waldo/actions/waldo_action.rb +13 -15
- data/lib/fastlane/plugin/waldo/assets/WaldoCLI.sh +672 -0
- data/lib/fastlane/plugin/waldo/helper/waldo_helper.rb +52 -379
- data/lib/fastlane/plugin/waldo/version.rb +1 -1
- metadata +10 -10
@@ -1,59 +1,20 @@
|
|
1
|
-
require 'base64'
|
2
|
-
require 'net/http'
|
3
|
-
|
4
1
|
module Fastlane
|
5
2
|
module Helper
|
6
3
|
class WaldoHelper
|
7
|
-
def self.convert_commit(sha)
|
8
|
-
puts "Entering convert_commit(#{sha})"
|
9
|
-
|
10
|
-
prefix = 'remotes/origin/'
|
11
|
-
pfxlen = prefix.length
|
12
|
-
|
13
|
-
full_name = get_git_commit_name(sha)
|
14
|
-
|
15
|
-
if full_name.start_with?(prefix)
|
16
|
-
abbr_name = full_name[pfxlen..-1]
|
17
|
-
else
|
18
|
-
abbr_name = "local:#{full_name}"
|
19
|
-
end
|
20
|
-
|
21
|
-
%("#{sha[0..7]}-#{abbr_name}")
|
22
|
-
end
|
23
|
-
|
24
|
-
def self.dump_request(request)
|
25
|
-
len = request.body ? request.body.length : 0
|
26
|
-
|
27
|
-
puts "Request: #{request.method} #{request.path} (#{len} bytes)"
|
28
|
-
|
29
|
-
request.each_capitalized do |key, value|
|
30
|
-
puts " #{key}: #{value}"
|
31
|
-
end
|
32
|
-
|
33
|
-
puts '-------'
|
34
|
-
end
|
35
|
-
|
36
|
-
def self.dump_response(response)
|
37
|
-
puts "Response: #{response.code} #{response.message} (#{response.body.length} bytes)"
|
38
|
-
|
39
|
-
response.each_capitalized do |key, value|
|
40
|
-
puts " #{key}: #{value}"
|
41
|
-
end
|
42
|
-
|
43
|
-
puts "#{response.body}"
|
44
|
-
end
|
45
|
-
|
46
4
|
def self.filter_parameters(in_params)
|
47
5
|
out_params = {}
|
48
6
|
|
49
7
|
apk_path = in_params[:apk_path]
|
50
8
|
app_path = in_params[:app_path]
|
9
|
+
dsym_path = in_params[:dsym_path]
|
10
|
+
include_symbols = in_params[:include_symbols]
|
51
11
|
ipa_path = in_params[:ipa_path]
|
52
12
|
upload_token = in_params[:upload_token]
|
53
|
-
variant_name = in_params[:variant_name]
|
13
|
+
variant_name = in_params[:variant_name] || Actions.lane_context[Actions::SharedValues::GRADLE_BUILD_TYPE]
|
54
14
|
|
55
15
|
apk_path.gsub!("\\ ", ' ') if apk_path
|
56
16
|
app_path.gsub!("\\ ", ' ') if app_path
|
17
|
+
dsym_path.gsub!("\\ ", ' ') if dsym_path
|
57
18
|
ipa_path.gsub!("\\ ", ' ') if ipa_path
|
58
19
|
|
59
20
|
out_params[:apk_path] = apk_path if apk_path
|
@@ -61,387 +22,99 @@ module Fastlane
|
|
61
22
|
if app_path && ipa_path
|
62
23
|
if !File.exist?(app_path)
|
63
24
|
out_params[:ipa_path] = ipa_path
|
25
|
+
|
26
|
+
app_path = nil
|
64
27
|
elsif !File.exist?(ipa_path)
|
65
28
|
out_params[:app_path] = app_path
|
29
|
+
|
30
|
+
ipa_path = nil
|
66
31
|
elsif File.mtime(app_path) < File.mtime(ipa_path)
|
67
32
|
out_params[:ipa_path] = ipa_path
|
33
|
+
|
34
|
+
app_path = nil
|
68
35
|
else
|
69
36
|
out_params[:app_path] = app_path
|
37
|
+
|
38
|
+
ipa_path = nil
|
70
39
|
end
|
71
40
|
else
|
72
41
|
out_params[:app_path] = app_path if app_path
|
73
42
|
out_params[:ipa_path] = ipa_path if ipa_path
|
74
43
|
end
|
75
44
|
|
76
|
-
|
45
|
+
if app_path
|
46
|
+
out_params[:dsym_path] = dsym_path if dsym_path
|
47
|
+
out_params[:include_symbols] = include_symbols if include_symbols
|
48
|
+
else
|
49
|
+
out_params[:dsym_path] = dsym_path if dsym_path && ipa_path
|
50
|
+
end
|
51
|
+
|
52
|
+
out_params[:upload_token] = upload_token if upload_token
|
77
53
|
out_params[:variant_name] = variant_name if variant_name
|
78
54
|
|
79
55
|
out_params
|
80
56
|
end
|
81
57
|
|
82
|
-
def self.get_authorization
|
83
|
-
"Upload-Token #{@upload_token}"
|
84
|
-
end
|
85
|
-
|
86
58
|
def self.get_flavor
|
87
59
|
case get_platform
|
88
60
|
when :android
|
89
|
-
|
61
|
+
'Android'
|
90
62
|
when :ios
|
91
|
-
|
63
|
+
'iOS'
|
92
64
|
else
|
93
|
-
|
65
|
+
'unknown'
|
94
66
|
end
|
95
67
|
end
|
96
68
|
|
97
|
-
def self.get_git_commit_name(sha)
|
98
|
-
cmd = %(git name-rev --exclude='tags/*' --name-only "#{sha}")
|
99
|
-
|
100
|
-
puts "Calling: #{cmd}" if FastlaneCore::Globals.verbose?
|
101
|
-
|
102
|
-
result = Actions.sh(cmd, log: false).chomp
|
103
|
-
|
104
|
-
puts "#{cmd} => #{result}" if FastlaneCore::Globals.verbose?
|
105
|
-
|
106
|
-
result
|
107
|
-
end
|
108
|
-
|
109
|
-
def self.get_git_commits
|
110
|
-
cmd = %(git log --format=%H -50)
|
111
|
-
|
112
|
-
result = Actions.sh(cmd, log: false).chomp
|
113
|
-
|
114
|
-
puts "#{cmd} => #{result}" if FastlaneCore::Globals.verbose?
|
115
|
-
|
116
|
-
result.split(' ')
|
117
|
-
end
|
118
|
-
|
119
|
-
def self.get_history
|
120
|
-
history = get_git_commits
|
121
|
-
|
122
|
-
return '' unless !history.empty?
|
123
|
-
|
124
|
-
history = history.map { |sha| convert_commit(sha) }
|
125
|
-
|
126
|
-
Base64.strict_encode64("[#{history.join(',')}]")
|
127
|
-
end
|
128
|
-
|
129
69
|
def self.get_platform
|
130
70
|
Actions.lane_context[Actions::SharedValues::PLATFORM_NAME] || :ios
|
131
71
|
end
|
132
72
|
|
133
|
-
def self.
|
134
|
-
|
135
|
-
end
|
136
|
-
|
137
|
-
def self.handle_error(message)
|
138
|
-
UI.error(message)
|
139
|
-
|
140
|
-
UI.error('No token for error report upload to Waldo!') unless @upload_token
|
141
|
-
|
142
|
-
upload_error(message) if @upload_token
|
143
|
-
end
|
144
|
-
|
145
|
-
def self.has_git_command?
|
146
|
-
cmd = %(which git)
|
147
|
-
|
148
|
-
result = Actions.sh(cmd, log: false).chomp
|
149
|
-
|
150
|
-
puts "#{cmd} => #{result}" if FastlaneCore::Globals.verbose?
|
151
|
-
|
152
|
-
!result.empty?
|
153
|
-
end
|
154
|
-
|
155
|
-
def self.is_git_repository?
|
156
|
-
cmd = %(git rev-parse)
|
157
|
-
|
158
|
-
result = true
|
159
|
-
|
160
|
-
Actions.sh(cmd,
|
161
|
-
log: false,
|
162
|
-
error_callback: ->(ignore) { result = false }
|
163
|
-
).chomp
|
164
|
-
|
165
|
-
puts "#{cmd} => #{result}" if FastlaneCore::Globals.verbose?
|
166
|
-
|
167
|
-
result
|
168
|
-
end
|
169
|
-
|
170
|
-
def self.make_build_request(uri)
|
171
|
-
if @apk_path
|
172
|
-
body_path = @apk_path
|
173
|
-
elsif @ipa_path
|
174
|
-
body_path = @ipa_path
|
175
|
-
else
|
176
|
-
app_basename = File.basename(@app_path)
|
177
|
-
app_dirname = File.dirname(@app_path)
|
178
|
-
|
179
|
-
body_path = File.join(Dir.tmpdir, "#{app_basename}.zip")
|
180
|
-
|
181
|
-
unless zip(src_path: app_basename,
|
182
|
-
zip_path: body_path,
|
183
|
-
cd_path: app_dirname)
|
184
|
-
return nil
|
185
|
-
end
|
186
|
-
end
|
73
|
+
def self.get_script_path
|
74
|
+
root = Pathname.new(File.expand_path('../../..', __FILE__))
|
187
75
|
|
188
|
-
|
189
|
-
|
190
|
-
request['Authorization'] = get_authorization
|
191
|
-
request['Transfer-Encoding'] = 'chunked'
|
192
|
-
request['User-Agent'] = get_user_agent
|
193
|
-
|
194
|
-
request.body_stream = WaldoReadIO.new(body_path)
|
195
|
-
|
196
|
-
if @app_path
|
197
|
-
request.content_type = 'application/zip'
|
198
|
-
else
|
199
|
-
request.content_type = 'application/octet-stream'
|
200
|
-
end
|
201
|
-
|
202
|
-
request
|
76
|
+
File.join(root, 'waldo', 'assets', 'WaldoCLI.sh')
|
203
77
|
end
|
204
78
|
|
205
|
-
def self.
|
206
|
-
|
207
|
-
history_error = "noGitCommandFound"
|
208
|
-
elsif !is_git_repository?
|
209
|
-
history_error = "notGitRepository"
|
210
|
-
else
|
211
|
-
history = get_history
|
212
|
-
end
|
213
|
-
|
214
|
-
query = ''
|
215
|
-
|
216
|
-
if history
|
217
|
-
query += "&history=#{history}"
|
218
|
-
elsif history_error
|
219
|
-
query += "&historyError=#{history_error}"
|
220
|
-
end
|
221
|
-
|
222
|
-
query += "&variantName=#{@variant_name}" if @variant_name
|
223
|
-
|
224
|
-
uri_string = 'https://api.waldo.io/versions'
|
225
|
-
|
226
|
-
uri_string += "?#{query[1..-1]}" if !query.empty?
|
227
|
-
|
228
|
-
URI(uri_string)
|
229
|
-
end
|
230
|
-
|
231
|
-
def self.make_error_request(uri, message)
|
232
|
-
request = Net::HTTP::Post.new(uri.request_uri)
|
233
|
-
|
234
|
-
request['Authorization'] = get_authorization
|
235
|
-
request['User-Agent'] = get_user_agent
|
236
|
-
|
237
|
-
request.body = { "message": message }.to_json
|
238
|
-
request.content_type = 'application/json'
|
239
|
-
|
240
|
-
request
|
241
|
-
end
|
242
|
-
|
243
|
-
def self.make_error_uri
|
244
|
-
uri_string = 'https://api.waldo.io/uploadError'
|
245
|
-
|
246
|
-
URI(uri_string)
|
247
|
-
end
|
248
|
-
|
249
|
-
def self.parse_build_response(response)
|
250
|
-
dump_response(response) if FastlaneCore::Globals.verbose?
|
251
|
-
|
252
|
-
case response.code.to_i
|
253
|
-
when 200..299
|
254
|
-
UI.success('Build successfully uploaded to Waldo!')
|
255
|
-
when 401
|
256
|
-
handle_error('Token is invalid or missing for build upload to Waldo!')
|
257
|
-
else
|
258
|
-
handle_error("Build failed to upload to Waldo: #{response.code} #{response.message}")
|
259
|
-
end
|
79
|
+
def self.get_user_agent
|
80
|
+
"Waldo fastlane/#{get_flavor} v#{Fastlane::Waldo::VERSION}"
|
260
81
|
end
|
261
82
|
|
262
|
-
def self.
|
263
|
-
|
83
|
+
def self.upload_build_with_symbols(params)
|
84
|
+
apk_path = params[:apk_path]
|
85
|
+
app_path = params[:app_path]
|
86
|
+
ipa_path = params[:ipa_path]
|
264
87
|
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
88
|
+
if apk_path
|
89
|
+
build_path = apk_path
|
90
|
+
elsif app_path
|
91
|
+
build_path = app_path
|
92
|
+
elsif ipa_path
|
93
|
+
build_path = ipa_path
|
270
94
|
else
|
271
|
-
|
272
|
-
end
|
273
|
-
end
|
274
|
-
|
275
|
-
def self.upload_build
|
276
|
-
begin
|
277
|
-
@variant_name ||= Actions.lane_context[Actions::SharedValues::GRADLE_BUILD_TYPE]
|
278
|
-
|
279
|
-
uri = make_build_uri
|
280
|
-
|
281
|
-
request = make_build_request(uri)
|
282
|
-
|
283
|
-
return unless request
|
284
|
-
|
285
|
-
UI.success('Uploading the build to Waldo. This could take a while…')
|
286
|
-
|
287
|
-
dump_request(request) if FastlaneCore::Globals.verbose?
|
288
|
-
|
289
|
-
Net::HTTP.start(uri.host, uri.port, :use_ssl => true) do |http|
|
290
|
-
http.read_timeout = 120 # 2 minutes
|
291
|
-
|
292
|
-
parse_build_response(http.request(request))
|
293
|
-
end
|
294
|
-
rescue Net::ReadTimeout => exc
|
295
|
-
handle_error('Build upload to Waldo timed out!')
|
296
|
-
rescue => exc
|
297
|
-
handle_error("Something went wrong uploading build to Waldo: #{exc.inspect.to_s}")
|
298
|
-
ensure
|
299
|
-
request.body_stream.close if request && request.body_stream
|
95
|
+
build_path = ""
|
300
96
|
end
|
301
|
-
end
|
302
97
|
|
303
|
-
|
304
|
-
begin
|
305
|
-
uri = make_error_uri
|
98
|
+
command = []
|
306
99
|
|
307
|
-
|
100
|
+
command << "WALDO_UPLOAD_TOKEN='#{params[:upload_token]}'"
|
101
|
+
command << "WALDO_USER_AGENT_OVERRIDE='#{get_user_agent}'"
|
102
|
+
command << "WALDO_VARIANT_NAME='#{params[:variant_name]}'" if params[:variant_name]
|
308
103
|
|
309
|
-
|
104
|
+
command << get_script_path.shellescape
|
310
105
|
|
311
|
-
|
106
|
+
command << '--include_symbols' if params[:include_symbols]
|
107
|
+
command << '--verbose' if FastlaneCore::Globals.verbose?
|
312
108
|
|
313
|
-
|
314
|
-
|
109
|
+
command << build_path.shellescape
|
110
|
+
command << params[:dsym_path].shellescape if params[:dsym_path]
|
315
111
|
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
rescue => exc
|
321
|
-
UI.error("Something went wrong uploading error report to Waldo: #{exc.inspect.to_s}")
|
112
|
+
Actions.sh_control_output(command.join(' '),
|
113
|
+
print_command: FastlaneCore::Globals.verbose?,
|
114
|
+
print_command_output: true) do |error|
|
115
|
+
# do nothing special, for now
|
322
116
|
end
|
323
117
|
end
|
324
|
-
|
325
|
-
def self.validate_parameters(params)
|
326
|
-
@apk_path = params[:apk_path]
|
327
|
-
@app_path = params[:app_path]
|
328
|
-
@ipa_path = params[:ipa_path]
|
329
|
-
@upload_token = params[:upload_token]
|
330
|
-
@variant_name = params[:variant_name]
|
331
|
-
|
332
|
-
unless @upload_token
|
333
|
-
handle_error('You must pass a nonempty upload token to the Waldo action')
|
334
|
-
|
335
|
-
return false
|
336
|
-
end
|
337
|
-
|
338
|
-
case get_platform
|
339
|
-
when :android
|
340
|
-
unless @apk_path
|
341
|
-
handle_error('You must pass an APK path to the Waldo action')
|
342
|
-
|
343
|
-
return false
|
344
|
-
end
|
345
|
-
|
346
|
-
unless File.exist?(@apk_path)
|
347
|
-
handle_error("Unable to find APK at path '#{@apk_path.to_s}'")
|
348
|
-
|
349
|
-
return false
|
350
|
-
end
|
351
|
-
|
352
|
-
unless File.file?(@apk_path) && File.readable?(@apk_path)
|
353
|
-
handle_error("Unable to read APK at path '#{@apk_path.to_s}'")
|
354
|
-
|
355
|
-
return false
|
356
|
-
end
|
357
|
-
when :ios
|
358
|
-
unless @app_path || @ipa_path
|
359
|
-
handle_error('You must pass an IPA or app path to the Waldo action')
|
360
|
-
|
361
|
-
return false
|
362
|
-
end
|
363
|
-
|
364
|
-
if @app_path
|
365
|
-
unless File.exist?(@app_path)
|
366
|
-
handle_error("Unable to find app at path '#{@app_path.to_s}'")
|
367
|
-
|
368
|
-
return false
|
369
|
-
end
|
370
|
-
|
371
|
-
unless File.directory?(@app_path) && File.readable?(@app_path)
|
372
|
-
handle_error("Unable to read app at path '#{@app_path.to_s}'")
|
373
|
-
|
374
|
-
return false
|
375
|
-
end
|
376
|
-
elsif @ipa_path
|
377
|
-
unless File.exist?(@ipa_path)
|
378
|
-
handle_error("Unable to find IPA at path '#{@ipa_path.to_s}'")
|
379
|
-
|
380
|
-
return false
|
381
|
-
end
|
382
|
-
|
383
|
-
unless File.file?(@ipa_path) && File.readable?(@ipa_path)
|
384
|
-
handle_error("Unable to read IPA at path '#{@ipa_path.to_s}'")
|
385
|
-
|
386
|
-
return false
|
387
|
-
end
|
388
|
-
end
|
389
|
-
else
|
390
|
-
handle_error("Unsupported platform: '#{get_platform.to_s}'")
|
391
|
-
|
392
|
-
return false
|
393
|
-
end
|
394
|
-
|
395
|
-
if @variant_name && @variant_name.empty?
|
396
|
-
handle_error('Empty variant name for Waldo given')
|
397
|
-
|
398
|
-
return false
|
399
|
-
end
|
400
|
-
|
401
|
-
return true
|
402
|
-
end
|
403
|
-
|
404
|
-
def self.zip(src_path:, zip_path:, cd_path:)
|
405
|
-
unless FastlaneCore::CommandExecutor.which('zip')
|
406
|
-
handle_error("Command not found: 'zip'")
|
407
|
-
|
408
|
-
return false
|
409
|
-
end
|
410
|
-
|
411
|
-
FileUtils.cd(cd_path) do
|
412
|
-
cmd = %(zip -qry "#{zip_path}" "#{src_path}")
|
413
|
-
|
414
|
-
result = Actions.sh(cmd, log: false)
|
415
|
-
|
416
|
-
puts "#{cmd} => #{result}" if FastlaneCore::Globals.verbose?
|
417
|
-
|
418
|
-
unless result.empty?
|
419
|
-
handle_error("Unable to zip app at path '#{src_path.to_s}' into '#{zip_path.to_s}'")
|
420
|
-
|
421
|
-
return false
|
422
|
-
end
|
423
|
-
end
|
424
|
-
|
425
|
-
return true
|
426
|
-
end
|
427
|
-
end
|
428
|
-
|
429
|
-
class WaldoReadIO
|
430
|
-
def initialize(path)
|
431
|
-
@fp = File.open(path)
|
432
|
-
end
|
433
|
-
|
434
|
-
def close
|
435
|
-
@fp.close
|
436
|
-
end
|
437
|
-
|
438
|
-
def read(length = nil, outbuf = nil)
|
439
|
-
if result = @fp.read(length, outbuf)
|
440
|
-
result.force_encoding('BINARY') if result.respond_to?(:force_encoding)
|
441
|
-
end
|
442
|
-
|
443
|
-
result
|
444
|
-
end
|
445
118
|
end
|
446
119
|
end
|
447
120
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fastlane-plugin-waldo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- J. G. Pusey
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-10-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -30,14 +30,14 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
33
|
+
version: 2.192.0
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
40
|
+
version: 2.192.0
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: pry
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -66,7 +66,7 @@ dependencies:
|
|
66
66
|
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
|
-
description:
|
69
|
+
description:
|
70
70
|
email: john@waldo.io
|
71
71
|
executables: []
|
72
72
|
extensions: []
|
@@ -76,13 +76,14 @@ files:
|
|
76
76
|
- README.md
|
77
77
|
- lib/fastlane/plugin/waldo.rb
|
78
78
|
- lib/fastlane/plugin/waldo/actions/waldo_action.rb
|
79
|
+
- lib/fastlane/plugin/waldo/assets/WaldoCLI.sh
|
79
80
|
- lib/fastlane/plugin/waldo/helper/waldo_helper.rb
|
80
81
|
- lib/fastlane/plugin/waldo/version.rb
|
81
82
|
homepage: https://github.com/waldoapp/fastlane-plugin-waldo
|
82
83
|
licenses:
|
83
84
|
- MIT
|
84
85
|
metadata: {}
|
85
|
-
post_install_message:
|
86
|
+
post_install_message:
|
86
87
|
rdoc_options: []
|
87
88
|
require_paths:
|
88
89
|
- lib
|
@@ -97,9 +98,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
97
98
|
- !ruby/object:Gem::Version
|
98
99
|
version: '0'
|
99
100
|
requirements: []
|
100
|
-
|
101
|
-
|
102
|
-
signing_key:
|
101
|
+
rubygems_version: 3.0.3
|
102
|
+
signing_key:
|
103
103
|
specification_version: 4
|
104
104
|
summary: Upload build to Waldo
|
105
105
|
test_files: []
|