fastlane-plugin-polidea 3.0.0 → 4.0.0.pre
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/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 +9 -8
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,14 +1,14 @@
|
|
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
|
@@ -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:
|