fastlane-plugin-polidea 3.0.1 → 4.0.0.pre
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/fastlane/plugin/polidea/actions/fota_s3.rb +80 -440
- data/lib/fastlane/plugin/polidea/actions/shuttle.rb +0 -27
- data/lib/fastlane/plugin/polidea/helper/s3.rb +31 -0
- data/lib/fastlane/plugin/polidea/helper/shuttle.rb +9 -3
- data/lib/fastlane/plugin/polidea/version.rb +1 -1
- metadata +13 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 462dc216c29617a3deac078635060a2df56673ea0d6a44b581efb69ebd84d6a8
|
4
|
+
data.tar.gz: d5507370c0f2c3e9bcdfa890e577a2efbc99e8b938448d89fad5bd9f742e9304
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4db6083677d5839abc5cc7be16d56379d4467b6be133fec45abbfc81e4a80c3b1fe007d72824da58f079a92783d48d8719daa7a374f7bc4d71c0cd80ae6c6eb0
|
7
|
+
data.tar.gz: 3d6846123c27d20dfa07fc5038b39c8d6df6a393abbe270331d0ece0111f3dfd3192f152633afcbcbfbf22f51d8b2df92300be7563b5d919a261bc74e975e94b
|
@@ -1,5 +1,4 @@
|
|
1
|
-
|
2
|
-
# rubocop:disable Metrics/ClassLength
|
1
|
+
|
3
2
|
require 'fastlane/erb_template_helper'
|
4
3
|
require 'ostruct'
|
5
4
|
require 'securerandom'
|
@@ -9,12 +8,8 @@ module Fastlane
|
|
9
8
|
module SharedValues
|
10
9
|
S3_IPA_OUTPUT_PATH = :S3_IPA_OUTPUT_PATH
|
11
10
|
S3_DSYM_OUTPUT_PATH = :S3_DSYM_OUTPUT_PATH
|
12
|
-
S3_PLIST_OUTPUT_PATH = :S3_PLIST_OUTPUT_PATH
|
13
11
|
S3_APK_OUTPUT_PATH = :S3_APK_OUTPUT_PATH
|
14
12
|
S3_MAPPING_OUTPUT_PATH = :S3_MAPPING_OUTPUT_PATH
|
15
|
-
S3_HTML_OUTPUT_PATH = :S3_HTML_OUTPUT_PATH
|
16
|
-
S3_VERSION_OUTPUT_PATH = :S3_VERSION_OUTPUT_PATH
|
17
|
-
S3_ICON_OUTPUT_PATH = :S3_ICON_OUTPUT_PATH
|
18
13
|
end
|
19
14
|
|
20
15
|
class FotaS3Action < Action
|
@@ -27,425 +22,109 @@ module Fastlane
|
|
27
22
|
params = {}
|
28
23
|
params[:ipa] = config[:ipa]
|
29
24
|
params[:apk] = config[:apk]
|
30
|
-
params[:icon] = config[:icon]
|
31
25
|
params[:dsym] = config[:dsym]
|
32
26
|
params[:mapping] = config[:mapping]
|
33
|
-
params[:
|
34
|
-
params[:
|
35
|
-
params[:
|
36
|
-
params[:
|
37
|
-
params[:
|
38
|
-
|
39
|
-
params[:
|
40
|
-
params[:html_template_path] = config[:html_template_path]
|
41
|
-
params[:html_file_name] = config[:html_file_name]
|
42
|
-
params[:version_template_path] = config[:version_template_path]
|
43
|
-
params[:version_file_name] = config[:version_file_name]
|
44
|
-
params[:acl] = config[:acl]
|
45
|
-
params[:release_notes] = config[:release_notes]
|
46
|
-
params[:treat_bucket_as_domain_name] = config[:treat_bucket_as_domain_name]
|
27
|
+
params[:environment] = config[:environment]
|
28
|
+
params[:api_token] = config[:api_token]
|
29
|
+
params[:app_identifier] = config[:app_identifier]
|
30
|
+
params[:prefix_schema] = config[:prefix_schema]
|
31
|
+
params[:build_number] = config[:build_number]
|
32
|
+
|
33
|
+
shuttle_client = Shuttle::Client.new(base_url(params[:environment]), params[:api_token])
|
47
34
|
|
48
35
|
case platform
|
49
36
|
when :ios
|
50
|
-
upload_ios(params)
|
37
|
+
upload_ios(params, shuttle_client)
|
51
38
|
when :android
|
52
|
-
upload_android(params)
|
39
|
+
upload_android(params, shuttle_client)
|
53
40
|
end
|
54
41
|
|
55
42
|
Fastlane::Polidea.session.action_completed("fota_s3")
|
56
43
|
return true
|
57
44
|
end
|
58
45
|
|
59
|
-
def self.upload_ios(params)
|
46
|
+
def self.upload_ios(params, shuttle_client)
|
60
47
|
# Pulling parameters for other uses
|
61
|
-
s3_region = params[:region]
|
62
|
-
s3_subdomain = params[:region] ? "s3-#{params[:region]}" : "s3"
|
63
|
-
s3_access_key = params[:access_key]
|
64
|
-
s3_secret_access_key = params[:secret_access_key]
|
65
|
-
s3_bucket = params[:bucket]
|
66
48
|
ipa_file = params[:ipa]
|
67
|
-
icon_file = params[:icon]
|
68
49
|
dsym_file = params[:dsym]
|
69
|
-
|
70
|
-
|
71
|
-
treat_bucket_as_domain_name = params[:treat_bucket_as_domain_name]
|
50
|
+
app_identifier = params[:app_identifier]
|
51
|
+
prefix_schema = params[:prefix_schema]
|
72
52
|
|
73
|
-
validate(params)
|
74
53
|
UI.user_error!("No IPA file path given, pass using `ipa: 'ipa path'`") unless ipa_file.to_s.length > 0
|
75
54
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
# Gets info used for the plist
|
81
|
-
info = FastlaneCore::IpaFileAnalyser.fetch_info_plist_file(ipa_file)
|
82
|
-
|
83
|
-
build_number = info['CFBundleVersion']
|
84
|
-
bundle_id = info['CFBundleIdentifier']
|
85
|
-
bundle_version = info['CFBundleShortVersionString']
|
86
|
-
app_name = info['CFBundleDisplayName'] || info['CFBundleName']
|
87
|
-
full_version = "#{bundle_version}.#{build_number}"
|
88
|
-
url_part = get_url_part(app_name, "ios", bundle_version, build_number)
|
89
|
-
|
90
|
-
plist_template_path = params[:plist_template_path]
|
91
|
-
html_file_name = params[:html_file_name]
|
92
|
-
version_template_path = params[:version_template_path]
|
93
|
-
version_file_name = params[:version_file_name]
|
94
|
-
|
95
|
-
ipa_file_basename = File.basename(ipa_file)
|
96
|
-
ipa_file_name = "#{url_part}#{ipa_file_basename}"
|
97
|
-
ipa_file_data = File.open(ipa_file, 'rb')
|
98
|
-
|
99
|
-
ipa_url = self.upload_file(bucket, ipa_file_name, ipa_file_data, acl, treat_bucket_as_domain_name)
|
55
|
+
upload_urls = shuttle_client.get_upload_urls('ios', app_identifier, prefix_schema)
|
56
|
+
upload_build_url = upload_urls['buildUrl']
|
57
|
+
self.upload_file(upload_build_url, ipa_file)
|
100
58
|
|
101
59
|
# Setting action and environment variables
|
102
|
-
Actions.lane_context[SharedValues::S3_IPA_OUTPUT_PATH] =
|
103
|
-
ENV[SharedValues::S3_IPA_OUTPUT_PATH.to_s] =
|
60
|
+
Actions.lane_context[SharedValues::S3_IPA_OUTPUT_PATH] = upload_build_url
|
61
|
+
ENV[SharedValues::S3_IPA_OUTPUT_PATH.to_s] = upload_build_url
|
104
62
|
|
105
63
|
if dsym_file
|
106
|
-
|
107
|
-
|
108
|
-
dsym_file_data = File.open(dsym_file, 'rb')
|
109
|
-
|
110
|
-
dsym_url = self.upload_file(bucket, dsym_file_name, dsym_file_data, acl, treat_bucket_as_domain_name)
|
111
|
-
|
112
|
-
dsym_file_data.close
|
113
|
-
end
|
114
|
-
|
115
|
-
if params[:upload_metadata] == false
|
116
|
-
return true
|
64
|
+
upload_dsym_url = upload_urls['debugFileUrl']
|
65
|
+
self.upload_file(upload_url, dsym_file)
|
117
66
|
end
|
118
67
|
|
119
|
-
|
120
|
-
#
|
121
|
-
# html and plist building
|
122
|
-
#
|
123
|
-
#####################################
|
68
|
+
UI.success("Successfully uploaded ipa file")
|
124
69
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
html_file_name ||= "#{url_part}index.html"
|
130
|
-
html_resources_name = "#{url_part}installation-page"
|
131
|
-
|
132
|
-
version_file_name ||= "#{url_part}version.json"
|
133
|
-
|
134
|
-
# grabs module
|
135
|
-
eth = Fastlane::ErbTemplateHelper
|
136
|
-
|
137
|
-
# Creates plist from template
|
138
|
-
if plist_template_path && File.exist?(plist_template_path)
|
139
|
-
plist_template = eth.load_from_path(plist_template_path)
|
140
|
-
else
|
141
|
-
plist_template = eth.load("s3_plist_template")
|
142
|
-
end
|
143
|
-
plist_render = eth.render(plist_template, {
|
144
|
-
url: ipa_url,
|
145
|
-
ipa_url: ipa_url,
|
146
|
-
bundle_id: bundle_id,
|
147
|
-
build_number: build_number,
|
148
|
-
bundle_version: bundle_version,
|
149
|
-
title: app_name
|
150
|
-
})
|
151
|
-
|
152
|
-
# Gets icon from ipa and uploads it
|
153
|
-
icon_url = self.upload_icon(icon_file, url_part, bucket, acl, treat_bucket_as_domain_name)
|
154
|
-
|
155
|
-
# Creates html from template
|
156
|
-
html_render = PageGenerator.installation_page({
|
157
|
-
url: "itms-services://?action=download-manifest&url=#{URI.encode_www_form_component(plist_url)}",
|
158
|
-
app_version: bundle_version,
|
159
|
-
build_number: build_number,
|
160
|
-
app_name: app_name,
|
161
|
-
app_icon: icon_url,
|
162
|
-
platform: "ios",
|
163
|
-
release_notes: release_notes
|
164
|
-
})
|
165
|
-
|
166
|
-
# Creates version from template
|
167
|
-
if version_template_path && File.exist?(version_template_path)
|
168
|
-
version_template = eth.load_from_path(version_template_path)
|
169
|
-
else
|
170
|
-
version_template = eth.load("s3_version_template")
|
171
|
-
end
|
172
|
-
version_render = eth.render(version_template, {
|
173
|
-
url: plist_url,
|
174
|
-
plist_url: plist_url,
|
175
|
-
ipa_url: ipa_url,
|
176
|
-
build_number: build_number,
|
177
|
-
bundle_version: bundle_version,
|
178
|
-
full_version: full_version
|
179
|
-
})
|
180
|
-
|
181
|
-
#####################################
|
182
|
-
#
|
183
|
-
# html and plist uploading
|
184
|
-
#
|
185
|
-
#####################################
|
186
|
-
|
187
|
-
plist_url = self.upload_file(bucket, plist_file_name, plist_render, acl, treat_bucket_as_domain_name)
|
188
|
-
html_url = self.upload_file(bucket, html_file_name, html_render, acl, treat_bucket_as_domain_name)
|
189
|
-
self.upload_directory(bucket, html_resources_name, "#{__dir__}/../templates/installation-page", acl)
|
190
|
-
version_url = self.upload_file(bucket, version_file_name, version_render, acl, treat_bucket_as_domain_name)
|
191
|
-
|
192
|
-
# Setting action and environment variables
|
193
|
-
Actions.lane_context[SharedValues::S3_PLIST_OUTPUT_PATH] = plist_url
|
194
|
-
ENV[SharedValues::S3_PLIST_OUTPUT_PATH.to_s] = plist_url
|
195
|
-
|
196
|
-
Actions.lane_context[SharedValues::S3_HTML_OUTPUT_PATH] = html_url
|
197
|
-
ENV[SharedValues::S3_HTML_OUTPUT_PATH.to_s] = html_url
|
198
|
-
|
199
|
-
Actions.lane_context[SharedValues::S3_VERSION_OUTPUT_PATH] = version_url
|
200
|
-
ENV[SharedValues::S3_VERSION_OUTPUT_PATH.to_s] = version_url
|
201
|
-
|
202
|
-
UI.success("Successfully uploaded ipa file to '#{Actions.lane_context[SharedValues::S3_IPA_OUTPUT_PATH]}'")
|
203
|
-
UI.success("Successfully uploaded plist file to '#{Actions.lane_context[SharedValues::S3_PLIST_OUTPUT_PATH]}'")
|
204
|
-
UI.success("Successfully uploaded html file to '#{Actions.lane_context[SharedValues::S3_HTML_OUTPUT_PATH]}'")
|
205
|
-
UI.success("Successfully uploaded version file to '#{Actions.lane_context[SharedValues::S3_VERSION_OUTPUT_PATH]}'")
|
206
|
-
|
207
|
-
if icon_url
|
208
|
-
Actions.lane_context[SharedValues::S3_ICON_OUTPUT_PATH] = icon_url
|
209
|
-
ENV[SharedValues::S3_ICON_OUTPUT_PATH.to_s] = icon_url
|
210
|
-
UI.success("Successfully uploaded icon file to '#{Actions.lane_context[SharedValues::S3_ICON_OUTPUT_PATH]}'")
|
211
|
-
end
|
212
|
-
if dsym_url
|
213
|
-
Actions.lane_context[SharedValues::S3_DSYM_OUTPUT_PATH] = dsym_url
|
214
|
-
ENV[SharedValues::S3_DSYM_OUTPUT_PATH.to_s] = dsym_url
|
215
|
-
UI.success("Successfully uploaded dsym file to '#{Actions.lane_context[SharedValues::S3_DSYM_OUTPUT_PATH]}'")
|
70
|
+
if upload_dsym_url
|
71
|
+
Actions.lane_context[SharedValues::S3_DSYM_OUTPUT_PATH] = upload_dsym_url
|
72
|
+
ENV[SharedValues::S3_DSYM_OUTPUT_PATH.to_s] = upload_dsym_url
|
73
|
+
UI.success("Successfully uploaded dsym file")
|
216
74
|
end
|
217
75
|
end
|
218
76
|
|
219
|
-
def self.upload_android(params)
|
77
|
+
def self.upload_android(params, shuttle_client)
|
220
78
|
# Pulling parameters for other uses
|
221
|
-
s3_region = params[:region]
|
222
|
-
s3_access_key = params[:access_key]
|
223
|
-
s3_secret_access_key = params[:secret_access_key]
|
224
|
-
s3_bucket = params[:bucket]
|
225
79
|
apk_file = params[:apk]
|
226
|
-
icon_file = params[:icon]
|
227
80
|
mapping_file = params[:mapping]
|
228
|
-
|
229
|
-
|
230
|
-
treat_bucket_as_domain_name = params[:treat_bucket_as_domain_name]
|
81
|
+
app_identifier = params[:app_identifier]
|
82
|
+
build_number = params[:build_number]
|
231
83
|
|
232
|
-
validate(params)
|
233
84
|
UI.user_error!("No APK file path given, pass using `apk: 'apk path'`") unless apk_file.to_s.length > 0
|
234
85
|
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
# Gets info used from the apk manifest
|
240
|
-
manifest = Android::Apk.new(apk_file).manifest
|
241
|
-
|
242
|
-
app_name = manifest.label
|
243
|
-
build_number = manifest.version_code
|
244
|
-
app_version = manifest.version_name
|
245
|
-
url_part = get_url_part(app_name, "android", app_version, build_number)
|
246
|
-
|
247
|
-
html_file_name = params[:html_file_name]
|
248
|
-
|
249
|
-
apk_file_basename = File.basename(apk_file)
|
250
|
-
apk_file_name = "#{url_part}#{apk_file_basename}"
|
251
|
-
apk_file_data = File.open(apk_file, 'rb')
|
252
|
-
|
253
|
-
apk_url = self.upload_file(bucket, apk_file_name, apk_file_data, acl, treat_bucket_as_domain_name)
|
86
|
+
upload_urls = shuttle_client.get_upload_urls('android', app_identifier, build_number)
|
87
|
+
upload_build_url = upload_urls['buildUrl']
|
88
|
+
self.upload_file(upload_build_url, apk_file)
|
254
89
|
|
255
90
|
# Setting action and environment variables
|
256
|
-
Actions.lane_context[SharedValues::S3_APK_OUTPUT_PATH] =
|
257
|
-
ENV[SharedValues::S3_APK_OUTPUT_PATH.to_s] =
|
91
|
+
Actions.lane_context[SharedValues::S3_APK_OUTPUT_PATH] = upload_build_url
|
92
|
+
ENV[SharedValues::S3_APK_OUTPUT_PATH.to_s] = upload_build_url
|
258
93
|
|
259
94
|
if mapping_file
|
260
|
-
|
261
|
-
|
262
|
-
mapping_file_data = File.open(mapping_file, 'rb')
|
263
|
-
|
264
|
-
mapping_url = self.upload_file(bucket, mapping_file_name, mapping_file_data, acl, treat_bucket_as_domain_name)
|
95
|
+
upload_mapping_file_url = upload_urls['debugFileUrl']
|
96
|
+
self.upload_file(upload_mapping_file_url, mapping_file)
|
265
97
|
|
266
98
|
# Setting action and environment variables
|
267
|
-
Actions.lane_context[SharedValues::S3_MAPPING_OUTPUT_PATH] =
|
268
|
-
ENV[SharedValues::S3_MAPPING_OUTPUT_PATH.to_s] =
|
99
|
+
Actions.lane_context[SharedValues::S3_MAPPING_OUTPUT_PATH] = upload_mapping_file_url
|
100
|
+
ENV[SharedValues::S3_MAPPING_OUTPUT_PATH.to_s] = upload_mapping_file_url
|
269
101
|
|
270
|
-
mapping_file_data.close
|
271
102
|
end
|
272
103
|
|
273
|
-
|
274
|
-
#
|
275
|
-
# html building
|
276
|
-
#
|
277
|
-
#####################################
|
278
|
-
|
279
|
-
# Creating html names
|
280
|
-
|
281
|
-
html_file_name ||= "#{url_part}index.html"
|
282
|
-
html_resources_name = "#{url_part}installation-page"
|
283
|
-
|
284
|
-
# Gets icon from ipa and uploads it
|
285
|
-
icon_url = self.upload_icon(icon_file, url_part, bucket, acl, treat_bucket_as_domain_name)
|
286
|
-
|
287
|
-
# Creates html from template
|
288
|
-
html_render = PageGenerator.installation_page({
|
289
|
-
url: apk_url,
|
290
|
-
app_version: app_version,
|
291
|
-
build_number: build_number,
|
292
|
-
app_name: app_name,
|
293
|
-
app_icon: icon_url,
|
294
|
-
platform: "android",
|
295
|
-
release_notes: release_notes
|
296
|
-
})
|
297
|
-
|
298
|
-
html_url = self.upload_file(bucket, html_file_name, html_render, acl, treat_bucket_as_domain_name)
|
299
|
-
self.upload_directory(bucket, html_resources_name, "#{__dir__}/../templates/installation-page", acl)
|
104
|
+
UI.success("Successfully uploaded apk file")
|
300
105
|
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
UI.success("Successfully uploaded apk file to '#{Actions.lane_context[SharedValues::S3_APK_OUTPUT_PATH]}'")
|
305
|
-
UI.success("Successfully uploaded html file to '#{Actions.lane_context[SharedValues::S3_HTML_OUTPUT_PATH]}'")
|
306
|
-
|
307
|
-
if icon_url
|
308
|
-
Actions.lane_context[SharedValues::S3_ICON_OUTPUT_PATH] = icon_url
|
309
|
-
ENV[SharedValues::S3_ICON_OUTPUT_PATH.to_s] = icon_url
|
310
|
-
UI.success("Successfully uploaded icon file to '#{Actions.lane_context[SharedValues::S3_ICON_OUTPUT_PATH]}'")
|
311
|
-
end
|
312
|
-
if mapping_url
|
313
|
-
UI.success("Successfully uploaded mapping file to '#{Actions.lane_context[SharedValues::S3_MAPPING_OUTPUT_PATH]}'")
|
106
|
+
if upload_mapping_file_url
|
107
|
+
UI.success("Successfully uploaded mapping file")
|
314
108
|
end
|
315
109
|
end
|
316
110
|
|
317
|
-
def self.
|
318
|
-
|
319
|
-
|
320
|
-
s3_bucket = params[:bucket]
|
321
|
-
|
322
|
-
UI.user_error!("No S3 access key given, pass using `access_key: 'key'`") unless s3_access_key.to_s.length > 0
|
323
|
-
UI.user_error!("No S3 secret access key given, pass using `secret_access_key: 'secret key'`") unless s3_secret_access_key.to_s.length > 0
|
324
|
-
UI.user_error!("No S3 bucket given, pass using `bucket: 'bucket'`") unless s3_bucket.to_s.length > 0
|
111
|
+
def self.upload_file(url, build)
|
112
|
+
client = S3::Client.new
|
113
|
+
client.upload_file(url, build)
|
325
114
|
end
|
326
115
|
|
327
|
-
def self.
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
self.s3_client(s3_access_key, s3_secret_access_key, s3_region).bucket(s3_bucket)
|
334
|
-
end
|
335
|
-
|
336
|
-
def self.s3_client(s3_access_key, s3_secret_access_key, s3_region)
|
337
|
-
Actions.verify_gem!('aws-sdk-s3')
|
338
|
-
require 'aws-sdk-s3'
|
339
|
-
|
340
|
-
if s3_region
|
341
|
-
s3_client = Aws::S3::Resource.new(
|
342
|
-
access_key_id: s3_access_key,
|
343
|
-
secret_access_key: s3_secret_access_key,
|
344
|
-
region: s3_region
|
345
|
-
)
|
346
|
-
else
|
347
|
-
s3_client = Aws::S3::Resource.new(
|
348
|
-
access_key_id: s3_access_key,
|
349
|
-
secret_access_key: s3_secret_access_key
|
350
|
-
)
|
351
|
-
end
|
352
|
-
s3_client
|
353
|
-
end
|
354
|
-
|
355
|
-
def self.upload_file(bucket, file_name, file_data, acl, treat_bucket_as_domain_name)
|
356
|
-
obj = bucket.put_object({
|
357
|
-
key: file_name,
|
358
|
-
body: file_data,
|
359
|
-
acl: acl,
|
360
|
-
content_type: Mime.content_type_for_file(file_name)
|
361
|
-
})
|
362
|
-
|
363
|
-
# When you enable versioning on a S3 bucket,
|
364
|
-
# writing to an object will create an object version
|
365
|
-
# instead of replacing the existing object.
|
366
|
-
# http://docs.aws.amazon.com/AWSRubySDK/latest/AWS/S3/ObjectVersion.html
|
367
|
-
if obj.kind_of? Aws::S3::ObjectVersion
|
368
|
-
obj = obj.object
|
369
|
-
end
|
370
|
-
|
371
|
-
if treat_bucket_as_domain_name
|
372
|
-
# Return public url
|
373
|
-
shorten_url(obj.public_url.to_s)
|
374
|
-
else
|
375
|
-
obj.public_url.to_s
|
376
|
-
end
|
377
|
-
end
|
378
|
-
|
379
|
-
def self.upload_directory(bucket, directory_name, directory_path, acl)
|
380
|
-
files = files_at_path(directory_path)
|
381
|
-
|
382
|
-
files.each do |file|
|
383
|
-
local_path = directory_path + file
|
384
|
-
s3_path = directory_name + file
|
385
|
-
|
386
|
-
bucket.put_object({
|
387
|
-
key: s3_path,
|
388
|
-
body: File.open(local_path),
|
389
|
-
acl: acl,
|
390
|
-
content_type: Mime.content_type_for_file(local_path)
|
391
|
-
})
|
392
|
-
end
|
393
|
-
end
|
394
|
-
|
395
|
-
def self.files_at_path(path)
|
396
|
-
files = Dir.glob(path + "/**/*")
|
397
|
-
to_remove = []
|
398
|
-
files.each do |file|
|
399
|
-
if File.directory?(file)
|
400
|
-
to_remove.push file
|
401
|
-
else
|
402
|
-
file.slice! path
|
403
|
-
end
|
404
|
-
end
|
405
|
-
to_remove.each do |file|
|
406
|
-
files.delete file
|
407
|
-
end
|
408
|
-
return files
|
409
|
-
end
|
410
|
-
|
411
|
-
#
|
412
|
-
# NOT a fan of this as this was taken straight from Shenzhen
|
413
|
-
# https://github.com/nomad/shenzhen/blob/986792db5d4d16a80c865a2748ee96ba63644821/lib/shenzhen/plugins/s3.rb#L32
|
414
|
-
#
|
415
|
-
# Need to find a way to not use this copied method
|
416
|
-
#
|
417
|
-
# AGAIN, I am not happy about this right now.
|
418
|
-
# Using this for prototype reasons.
|
419
|
-
#
|
420
|
-
def self.expand_path_with_substitutions_from_ipa_plist(ipa, path)
|
421
|
-
substitutions = path.scan(/\{CFBundle[^}]+\}/)
|
422
|
-
return path if substitutions.empty?
|
423
|
-
info = FastlaneCore::IpaFileAnalyser.fetch_info_plist_file(ipa) or return path
|
424
|
-
|
425
|
-
substitutions.uniq.each do |substitution|
|
426
|
-
key = substitution[1...-1]
|
427
|
-
value = info[key]
|
428
|
-
path.gsub!(Regexp.new(substitution), value) if value
|
116
|
+
def self.base_url(environment)
|
117
|
+
case environment
|
118
|
+
when :production
|
119
|
+
"https://shuttle.polidea.com"
|
120
|
+
when :testing
|
121
|
+
"https://shuttle-testing.polidea.com"
|
429
122
|
end
|
430
|
-
|
431
|
-
return path
|
432
|
-
end
|
433
|
-
|
434
|
-
def self.upload_icon(icon_path, url_part, bucket, acl, treat_bucket_as_domain_name)
|
435
|
-
return unless icon_path
|
436
|
-
icon_file_basename = File.basename(icon_path)
|
437
|
-
icon_file = File.open(icon_path)
|
438
|
-
icon_file_name = "#{url_part}#{icon_file_basename}"
|
439
|
-
self.upload_file(bucket, icon_file_name, icon_file, acl, treat_bucket_as_domain_name)
|
440
|
-
end
|
441
|
-
|
442
|
-
def self.shorten_url(url)
|
443
|
-
uri = URI.parse(url)
|
444
|
-
uri.scheme + ':/' + uri.path
|
445
123
|
end
|
124
|
+
private_class_method :base_url
|
446
125
|
|
447
126
|
def self.description
|
448
|
-
"
|
127
|
+
"Uploads build to AWS S3"
|
449
128
|
end
|
450
129
|
|
451
130
|
def self.available_options
|
@@ -470,73 +149,38 @@ module Fastlane
|
|
470
149
|
description: "The path to the mapping.txt file",
|
471
150
|
optional: true,
|
472
151
|
default_value: Actions.lane_context[SharedValues::GRADLE_MAPPING_TXT_OUTPUT_PATH]),
|
473
|
-
FastlaneCore::ConfigItem.new(key: :icon,
|
474
|
-
env_name: "",
|
475
|
-
description: "app icon file to upload",
|
476
|
-
optional: true,
|
477
|
-
default_value: Actions.lane_context[SharedValues::ICON_OUTPUT_PATH]),
|
478
|
-
FastlaneCore::ConfigItem.new(key: :upload_metadata,
|
479
|
-
env_name: "",
|
480
|
-
description: "Upload relevant metadata for this build",
|
481
|
-
optional: true,
|
482
|
-
default_value: true,
|
483
|
-
is_string: false),
|
484
|
-
FastlaneCore::ConfigItem.new(key: :plist_template_path,
|
485
|
-
env_name: "",
|
486
|
-
description: "plist template path",
|
487
|
-
optional: true),
|
488
|
-
FastlaneCore::ConfigItem.new(key: :html_template_path,
|
489
|
-
env_name: "",
|
490
|
-
description: "html erb template path",
|
491
|
-
optional: true),
|
492
|
-
FastlaneCore::ConfigItem.new(key: :html_file_name,
|
493
|
-
env_name: "",
|
494
|
-
description: "uploaded html filename",
|
495
|
-
optional: true),
|
496
|
-
FastlaneCore::ConfigItem.new(key: :version_template_path,
|
497
|
-
env_name: "",
|
498
|
-
description: "version erb template path",
|
499
|
-
optional: true),
|
500
|
-
FastlaneCore::ConfigItem.new(key: :version_file_name,
|
501
|
-
env_name: "",
|
502
|
-
description: "uploaded version filename",
|
503
|
-
optional: true),
|
504
|
-
FastlaneCore::ConfigItem.new(key: :access_key,
|
505
|
-
env_name: "S3_ACCESS_KEY",
|
506
|
-
description: "AWS Access Key ID ",
|
507
|
-
optional: true,
|
508
|
-
default_value: ENV['AWS_ACCESS_KEY_ID']),
|
509
|
-
FastlaneCore::ConfigItem.new(key: :secret_access_key,
|
510
|
-
env_name: "S3_SECRET_ACCESS_KEY",
|
511
|
-
description: "AWS Secret Access Key ",
|
512
|
-
optional: true,
|
513
|
-
default_value: ENV['AWS_SECRET_ACCESS_KEY']),
|
514
|
-
FastlaneCore::ConfigItem.new(key: :bucket,
|
515
|
-
env_name: "S3_BUCKET",
|
516
|
-
description: "AWS bucket name",
|
517
|
-
optional: true,
|
518
|
-
default_value: ENV['AWS_BUCKET_NAME']),
|
519
|
-
FastlaneCore::ConfigItem.new(key: :region,
|
520
|
-
env_name: "S3_REGION",
|
521
|
-
description: "AWS region (for bucket creation) ",
|
522
|
-
optional: true,
|
523
|
-
default_value: ENV['AWS_REGION']),
|
524
|
-
FastlaneCore::ConfigItem.new(key: :acl,
|
525
|
-
env_name: "S3_ACL",
|
526
|
-
description: "Uploaded object permissions e.g public_read (default), private, public_read_write, authenticated_read ",
|
527
|
-
optional: true,
|
528
|
-
default_value: "public-read"),
|
529
|
-
FastlaneCore::ConfigItem.new(key: :release_notes,
|
530
|
-
env_name: "S3_RELEASE_NOTES",
|
531
|
-
description: "Release notes",
|
532
|
-
type: String,
|
533
|
-
optional: true,
|
534
|
-
default_value: Actions.lane_context[SharedValues::RELEASE_NOTES]),
|
535
152
|
FastlaneCore::ConfigItem.new(key: :treat_bucket_as_domain_name,
|
536
153
|
description: "If it's true, it transforms all urls from https://s3.amazonaws.com/BUCKET_NAME to https://BUCKET_NAME",
|
537
154
|
is_string: false,
|
538
155
|
optional: true,
|
539
|
-
default_value: true)
|
156
|
+
default_value: true),
|
157
|
+
FastlaneCore::ConfigItem.new(key: :environment,
|
158
|
+
description: "Select environment, defaults to :production",
|
159
|
+
type: Symbol,
|
160
|
+
default_value: :production,
|
161
|
+
optional: true),
|
162
|
+
FastlaneCore::ConfigItem.new(key: :api_token,
|
163
|
+
env_name: "SHUTTLE_API_TOKEN",
|
164
|
+
description: "API Token for Shuttle",
|
165
|
+
verify_block: proc do |api_token|
|
166
|
+
UI.user_error!("No API token for Shuttle given, pass using `api_token: 'token'`") unless api_token and !api_token.empty?
|
167
|
+
end),
|
168
|
+
FastlaneCore::ConfigItem.new(key: :app_identifier,
|
169
|
+
description: "App identifier, either bundle id or package name",
|
170
|
+
type: String,
|
171
|
+
default_value: Actions.lane_context[SharedValues::APP_IDENTIFIER]),
|
172
|
+
FastlaneCore::ConfigItem.new(key: :prefix_schema,
|
173
|
+
env_name: "SHUTTLE_PREFIX_SCHEMA",
|
174
|
+
description: "Prefix schema in uploaded app",
|
175
|
+
default_value: Actions.lane_context[SharedValues::PREFIX_SCHEMA],
|
176
|
+
optional: true),
|
177
|
+
FastlaneCore::ConfigItem.new(key: :build_number,
|
178
|
+
description: "Build number, eg. 1337",
|
179
|
+
is_string: false,
|
180
|
+
default_value: Actions.lane_context[SharedValues::BUILD_NUMBER],
|
181
|
+
verify_block: proc do |build_number|
|
182
|
+
UI.user_error!("No value found for 'build_number'") unless build_number and build_number.kind_of? Integer
|
183
|
+
end)
|
540
184
|
]
|
541
185
|
end
|
542
186
|
|
@@ -544,12 +188,8 @@ module Fastlane
|
|
544
188
|
[
|
545
189
|
['S3_IPA_OUTPUT_PATH', 'Direct HTTP link to the uploaded ipa file'],
|
546
190
|
['S3_DSYM_OUTPUT_PATH', 'Direct HTTP link to the uploaded dsym file'],
|
547
|
-
['S3_PLIST_OUTPUT_PATH', 'Direct HTTP link to the uploaded plist file'],
|
548
191
|
['S3_APK_OUTPUT_PATH', 'Direct HTTP link to the uploaded apk file'],
|
549
|
-
['S3_MAPPING_OUTPUT_PATH', 'Direct HTTP link to the uploaded mapping.txt file']
|
550
|
-
['S3_HTML_OUTPUT_PATH', 'Direct HTTP link to the uploaded HTML file'],
|
551
|
-
['S3_VERSION_OUTPUT_PATH', 'Direct HTTP link to the uploaded Version file'],
|
552
|
-
['S3_ICON_OUTPUT_PATH', 'Direct HTTP link to the uploaded icon file']
|
192
|
+
['S3_MAPPING_OUTPUT_PATH', 'Direct HTTP link to the uploaded mapping.txt file']
|
553
193
|
]
|
554
194
|
end
|
555
195
|
|
@@ -10,9 +10,7 @@ module Fastlane
|
|
10
10
|
platform = Actions.lane_context[Actions::SharedValues::PLATFORM_NAME].to_sym
|
11
11
|
options = {
|
12
12
|
api_token: params[:api_token],
|
13
|
-
plist_url: params[:plist_url],
|
14
13
|
prefix_schema: params[:prefix_schema],
|
15
|
-
apk_url: params[:apk_url],
|
16
14
|
app_identifier: params[:app_identifier],
|
17
15
|
app_version: params[:app_version],
|
18
16
|
build_number: params[:build_number],
|
@@ -54,21 +52,11 @@ module Fastlane
|
|
54
52
|
verify_block: proc do |api_token|
|
55
53
|
UI.user_error!("No API token for Shuttle given, pass using `api_token: 'token'`") unless api_token and !api_token.empty?
|
56
54
|
end),
|
57
|
-
FastlaneCore::ConfigItem.new(key: :plist_url,
|
58
|
-
env_name: "SHUTTLE_PLIST_URL",
|
59
|
-
description: "Url to uploaded plist",
|
60
|
-
default_value: Actions.lane_context[SharedValues::S3_PLIST_OUTPUT_PATH],
|
61
|
-
optional: true),
|
62
55
|
FastlaneCore::ConfigItem.new(key: :prefix_schema,
|
63
56
|
env_name: "SHUTTLE_PREFIX_SCHEMA",
|
64
57
|
description: "Prefix schema in uploaded app",
|
65
58
|
default_value: Actions.lane_context[SharedValues::PREFIX_SCHEMA],
|
66
59
|
optional: true),
|
67
|
-
FastlaneCore::ConfigItem.new(key: :apk_url,
|
68
|
-
env_name: "SHUTTLE_APK_URL",
|
69
|
-
description: "Url to uploaded apk",
|
70
|
-
default_value: Actions.lane_context[SharedValues::S3_APK_OUTPUT_PATH],
|
71
|
-
optional: true),
|
72
60
|
FastlaneCore::ConfigItem.new(key: :app_identifier,
|
73
61
|
description: "App identifier, either bundle id or package name",
|
74
62
|
type: String,
|
@@ -114,12 +102,7 @@ module Fastlane
|
|
114
102
|
|
115
103
|
def self.validate(platform, params)
|
116
104
|
case platform
|
117
|
-
when :android
|
118
|
-
apk_url = params[:apk_url]
|
119
|
-
UI.user_error!("No apk url given, pass using `apk_url: 'url'` or make sure s3 action succeded and exposed S3_APK_OUTPUT_PATH shared value") unless apk_url and !apk_url.empty?
|
120
105
|
when :ios
|
121
|
-
plist_url = params[:plist_url]
|
122
|
-
UI.user_error!("No plist url given, pass using `plist_url: 'url'` or make sure s3 action succeded and exposed S3_PLIST_OUTPUT_PATH shared value") unless plist_url and !plist_url.empty?
|
123
106
|
url_scheme = params[:prefix_schema]
|
124
107
|
UI.user_error!("No prefix scheme given. Make sure `add_prefix_schema` action succeded before build action") if url_scheme.nil?
|
125
108
|
end
|
@@ -136,10 +119,7 @@ module Fastlane
|
|
136
119
|
|
137
120
|
case platform
|
138
121
|
when :ios
|
139
|
-
href = itms_href(params[:plist_url])
|
140
122
|
prefix_schema = params[:prefix_schema]
|
141
|
-
when :android
|
142
|
-
href = params[:apk_url]
|
143
123
|
end
|
144
124
|
|
145
125
|
{
|
@@ -147,7 +127,6 @@ module Fastlane
|
|
147
127
|
app_identifier: app_identifier,
|
148
128
|
app_version: app_version,
|
149
129
|
build_number: build_number,
|
150
|
-
href: href,
|
151
130
|
release_notes: release_notes,
|
152
131
|
releaser: releaser,
|
153
132
|
binary_size: binary_size,
|
@@ -158,7 +137,6 @@ module Fastlane
|
|
158
137
|
|
159
138
|
def self.notify(platform, params)
|
160
139
|
build = {
|
161
|
-
href: params[:href],
|
162
140
|
version: params[:app_version],
|
163
141
|
releaseNotes: params[:release_notes],
|
164
142
|
bytes: params[:binary_size],
|
@@ -184,11 +162,6 @@ module Fastlane
|
|
184
162
|
end
|
185
163
|
private_class_method :base_url
|
186
164
|
|
187
|
-
def self.itms_href(plist_url)
|
188
|
-
"itms-services://?action=download-manifest&url=#{URI.encode_www_form_component(plist_url)}"
|
189
|
-
end
|
190
|
-
private_class_method :itms_href
|
191
|
-
|
192
165
|
def self.commit_author
|
193
166
|
sh("git --no-pager show -s --format='%ae'", print_command: false, print_command_output: false).strip
|
194
167
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module Fastlane
|
5
|
+
module S3
|
6
|
+
class Client
|
7
|
+
def upload_file(url, file)
|
8
|
+
retry_options = {
|
9
|
+
max: 2,
|
10
|
+
interval: 0.05,
|
11
|
+
interval_randomness: 0.5,
|
12
|
+
backoff_factor: 2
|
13
|
+
}
|
14
|
+
connection = Faraday.new(
|
15
|
+
url
|
16
|
+
) do |conn|
|
17
|
+
conn.request :retry, retry_options
|
18
|
+
conn.request :multipart
|
19
|
+
conn.response :raise_error
|
20
|
+
conn.adapter :net_http
|
21
|
+
end
|
22
|
+
payload = { file: Faraday::UploadIO.new(file, '') }
|
23
|
+
|
24
|
+
connection.put(
|
25
|
+
'',
|
26
|
+
payload.to_json
|
27
|
+
)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -21,19 +21,25 @@ module Fastlane
|
|
21
21
|
) do |conn|
|
22
22
|
conn.request :retry, retry_options
|
23
23
|
conn.request :multipart
|
24
|
-
|
25
24
|
conn.response :raise_error
|
26
|
-
|
25
|
+
conn.response :json
|
27
26
|
conn.adapter :net_http
|
28
27
|
end
|
29
28
|
end
|
30
29
|
|
31
30
|
def create_build(platform, app_identifier, build)
|
32
31
|
@conn.post(
|
33
|
-
"cd/apps/#{platform}/#{app_identifier}/builds",
|
32
|
+
"cd/apps/#{platform}/#{app_identifier}/builds/v2",
|
34
33
|
{ build: build }.to_json
|
35
34
|
)
|
36
35
|
end
|
36
|
+
|
37
|
+
def get_upload_urls(platform, app_id, build_identifier)
|
38
|
+
response = @conn.get(
|
39
|
+
"projects/apps/#{platform}/#{app_id}/builds/#{build_identifier}/upload-url/v2"
|
40
|
+
)
|
41
|
+
return response.body
|
42
|
+
end
|
37
43
|
end
|
38
44
|
end
|
39
45
|
end
|
metadata
CHANGED
@@ -1,29 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fastlane-plugin-polidea
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 4.0.0.pre
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Piotrek Dubiel
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-09-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 0.17.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 0.17.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: plist
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -230,16 +230,16 @@ dependencies:
|
|
230
230
|
name: simplecov
|
231
231
|
requirement: !ruby/object:Gem::Requirement
|
232
232
|
requirements:
|
233
|
-
- -
|
233
|
+
- - '='
|
234
234
|
- !ruby/object:Gem::Version
|
235
|
-
version: '0'
|
235
|
+
version: '0.17'
|
236
236
|
type: :development
|
237
237
|
prerelease: false
|
238
238
|
version_requirements: !ruby/object:Gem::Requirement
|
239
239
|
requirements:
|
240
|
-
- -
|
240
|
+
- - '='
|
241
241
|
- !ruby/object:Gem::Version
|
242
|
-
version: '0'
|
242
|
+
version: '0.17'
|
243
243
|
- !ruby/object:Gem::Dependency
|
244
244
|
name: fastlane
|
245
245
|
requirement: !ruby/object:Gem::Requirement
|
@@ -275,6 +275,7 @@ files:
|
|
275
275
|
- lib/fastlane/plugin/polidea/helper/mime.rb
|
276
276
|
- lib/fastlane/plugin/polidea/helper/page_generator.rb
|
277
277
|
- lib/fastlane/plugin/polidea/helper/qr_generator.rb
|
278
|
+
- lib/fastlane/plugin/polidea/helper/s3.rb
|
278
279
|
- lib/fastlane/plugin/polidea/helper/shuttle.rb
|
279
280
|
- lib/fastlane/plugin/polidea/version.rb
|
280
281
|
- templates/install.erb
|
@@ -294,9 +295,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
294
295
|
version: '0'
|
295
296
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
296
297
|
requirements:
|
297
|
-
- - "
|
298
|
+
- - ">"
|
298
299
|
- !ruby/object:Gem::Version
|
299
|
-
version:
|
300
|
+
version: 1.3.1
|
300
301
|
requirements: []
|
301
302
|
rubygems_version: 3.0.1
|
302
303
|
signing_key:
|