fastlane-plugin-polidea 3.0.0 → 4.0.0.pre.3
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/README.md +1 -6
- data/lib/fastlane/plugin/polidea/actions/shuttle.rb +73 -32
- data/lib/fastlane/plugin/polidea/helper/s3.rb +30 -0
- data/lib/fastlane/plugin/polidea/helper/shuttle.rb +9 -3
- data/lib/fastlane/plugin/polidea/version.rb +1 -1
- metadata +9 -10
- data/lib/fastlane/plugin/polidea/actions/fota_mail.rb +0 -187
- data/lib/fastlane/plugin/polidea/actions/fota_s3.rb +0 -568
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e96d20dc3d82e5d9eb608192437fe2f96a8b6e5d56d66064b11bc06be1f3bdff
|
4
|
+
data.tar.gz: 550ae76e8bd178dad28d8305a16d5870dffdb5872c8a986d7dcd15f8acadcc91
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2dbb128516aac0a303cac31eeb583244f163de0aefe511465dc6908fbff12d1b25aaf97e74a0d5a6ba8ef2a6a1bdf316b6777277686c5e0107856ceb8999e67c
|
7
|
+
data.tar.gz: aa072fe85f8c5df7c18f706c18868b87243cc6da3457908625af9c263818e20346d4318906c393ae1330c5b848e2962fab753e20b3140566abdd31d1c416be8e
|
data/README.md
CHANGED
@@ -17,8 +17,6 @@ fastlane add_plugin polidea
|
|
17
17
|
Plugin contains following actions:
|
18
18
|
- `extract_app_info`: Extracts application name, icon, version, binary size from .apk/.ipa
|
19
19
|
- `release_notes`: Extracts release notes from git tag message
|
20
|
-
- `fota_s3`: Custom version of s3 action with Polidea's installation page
|
21
|
-
- `fota_mail`: Custom version of mailgun action with Polidea's mail template
|
22
20
|
- `shuttle`: Upload new app to Shuttle
|
23
21
|
|
24
22
|
See more details [here](./docs/Actions.md).
|
@@ -33,10 +31,7 @@ fastlane actions
|
|
33
31
|
lane :deploy do
|
34
32
|
(some actions that produces .ipa/.apk)
|
35
33
|
extract_app_info
|
36
|
-
|
37
|
-
fota_mail(
|
38
|
-
to: "hey@polidea.com"
|
39
|
-
)
|
34
|
+
shuttle
|
40
35
|
end
|
41
36
|
```
|
42
37
|
|
@@ -10,9 +10,11 @@ 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
|
-
|
13
|
+
ipa: params[:ipa],
|
14
|
+
apk: params[:apk],
|
15
|
+
dsym: params[:dsym],
|
16
|
+
mapping: params[:mapping],
|
14
17
|
prefix_schema: params[:prefix_schema],
|
15
|
-
apk_url: params[:apk_url],
|
16
18
|
app_identifier: params[:app_identifier],
|
17
19
|
app_version: params[:app_version],
|
18
20
|
build_number: params[:build_number],
|
@@ -23,7 +25,9 @@ module Fastlane
|
|
23
25
|
}
|
24
26
|
validate(platform, options)
|
25
27
|
config = get_config(platform, options)
|
26
|
-
|
28
|
+
client = Shuttle::Client.new(base_url(params[:environment]), params[:api_token])
|
29
|
+
notify(client, platform, config)
|
30
|
+
upload(client, platform, config)
|
27
31
|
|
28
32
|
UI.success("Successfully uploaded to #{params[:app_identifier]} #{params[:app_version]}.#{params[:build_number]} to Shuttle")
|
29
33
|
|
@@ -54,21 +58,31 @@ module Fastlane
|
|
54
58
|
verify_block: proc do |api_token|
|
55
59
|
UI.user_error!("No API token for Shuttle given, pass using `api_token: 'token'`") unless api_token and !api_token.empty?
|
56
60
|
end),
|
57
|
-
FastlaneCore::ConfigItem.new(key: :
|
58
|
-
env_name: "
|
59
|
-
description: "
|
60
|
-
|
61
|
-
|
61
|
+
FastlaneCore::ConfigItem.new(key: :ipa,
|
62
|
+
env_name: "",
|
63
|
+
description: ".ipa file for the build",
|
64
|
+
optional: true,
|
65
|
+
default_value: Actions.lane_context[SharedValues::IPA_OUTPUT_PATH]),
|
66
|
+
FastlaneCore::ConfigItem.new(key: :dsym,
|
67
|
+
env_name: "",
|
68
|
+
description: "zipped .dsym package for the build",
|
69
|
+
optional: true,
|
70
|
+
default_value: Actions.lane_context[SharedValues::DSYM_OUTPUT_PATH]),
|
71
|
+
FastlaneCore::ConfigItem.new(key: :apk,
|
72
|
+
env_name: "",
|
73
|
+
description: ".apk file for the build",
|
74
|
+
optional: true,
|
75
|
+
default_value: Actions.lane_context[SharedValues::GRADLE_APK_OUTPUT_PATH]),
|
76
|
+
FastlaneCore::ConfigItem.new(key: :mapping,
|
77
|
+
env_name: "",
|
78
|
+
description: "The path to the mapping.txt file",
|
79
|
+
optional: true,
|
80
|
+
default_value: Actions.lane_context[SharedValues::GRADLE_MAPPING_TXT_OUTPUT_PATH]),
|
62
81
|
FastlaneCore::ConfigItem.new(key: :prefix_schema,
|
63
82
|
env_name: "SHUTTLE_PREFIX_SCHEMA",
|
64
83
|
description: "Prefix schema in uploaded app",
|
65
84
|
default_value: Actions.lane_context[SharedValues::PREFIX_SCHEMA],
|
66
85
|
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
86
|
FastlaneCore::ConfigItem.new(key: :app_identifier,
|
73
87
|
description: "App identifier, either bundle id or package name",
|
74
88
|
type: String,
|
@@ -114,14 +128,14 @@ module Fastlane
|
|
114
128
|
|
115
129
|
def self.validate(platform, params)
|
116
130
|
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
131
|
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
132
|
url_scheme = params[:prefix_schema]
|
124
133
|
UI.user_error!("No prefix scheme given. Make sure `add_prefix_schema` action succeded before build action") if url_scheme.nil?
|
134
|
+
ipa = params[:ipa]
|
135
|
+
UI.user_error!("No .ipa file path given. Make sure `gym` action succeded") if ipa.nil?
|
136
|
+
when :android
|
137
|
+
apk = params[:apk]
|
138
|
+
UI.user_error!("No .apk file path given. Make sure `gradle` action succeded") if apk.nil?
|
125
139
|
end
|
126
140
|
end
|
127
141
|
|
@@ -135,11 +149,13 @@ module Fastlane
|
|
135
149
|
releaser = params[:releaser] || commit_author
|
136
150
|
|
137
151
|
case platform
|
152
|
+
when :android
|
153
|
+
apk = params[:apk]
|
154
|
+
mapping = params[:mapping]
|
138
155
|
when :ios
|
139
|
-
href = itms_href(params[:plist_url])
|
140
156
|
prefix_schema = params[:prefix_schema]
|
141
|
-
|
142
|
-
|
157
|
+
ipa = params[:ipa]
|
158
|
+
dsym = params[:dsym]
|
143
159
|
end
|
144
160
|
|
145
161
|
{
|
@@ -147,18 +163,20 @@ module Fastlane
|
|
147
163
|
app_identifier: app_identifier,
|
148
164
|
app_version: app_version,
|
149
165
|
build_number: build_number,
|
150
|
-
href: href,
|
151
166
|
release_notes: release_notes,
|
152
167
|
releaser: releaser,
|
153
168
|
binary_size: binary_size,
|
154
169
|
prefix_schema: prefix_schema,
|
155
|
-
environment: params[:environment]
|
170
|
+
environment: params[:environment],
|
171
|
+
ipa: ipa,
|
172
|
+
apk: apk,
|
173
|
+
mapping: mapping,
|
174
|
+
dsym: dsym
|
156
175
|
}
|
157
176
|
end
|
158
177
|
|
159
|
-
def self.notify(platform, params)
|
178
|
+
def self.notify(client, platform, params)
|
160
179
|
build = {
|
161
|
-
href: params[:href],
|
162
180
|
version: params[:app_version],
|
163
181
|
releaseNotes: params[:release_notes],
|
164
182
|
bytes: params[:binary_size],
|
@@ -168,12 +186,40 @@ module Fastlane
|
|
168
186
|
build[:prefixSchema] = params[:prefix_schema] if platform == :ios
|
169
187
|
build[:versionCode] = params[:build_number] if platform == :android
|
170
188
|
|
171
|
-
client = Shuttle::Client.new(base_url(params[:environment]), params[:api_token])
|
172
|
-
|
173
189
|
client.create_build(platform, params[:app_identifier], build)
|
174
190
|
end
|
175
191
|
private_class_method :notify
|
176
192
|
|
193
|
+
def self.upload(client, platform, params)
|
194
|
+
case platform
|
195
|
+
when :ios
|
196
|
+
upload_urls = client.get_upload_urls(platform, params[:app_identifier], params[:prefix_schema])
|
197
|
+
upload_build_url = upload_urls['buildUrl']
|
198
|
+
self.upload_file(upload_build_url, params[:ipa])
|
199
|
+
UI.success("Successfully uploaded ipa file")
|
200
|
+
if params[:dsym]
|
201
|
+
upload_dsym_url = upload_urls['debugFileUrl']
|
202
|
+
self.upload_file(upload_dsym_url, params[:dsym])
|
203
|
+
UI.success("Successfully uploaded dsym file")
|
204
|
+
end
|
205
|
+
when :android
|
206
|
+
upload_urls = client.get_upload_urls(platform, params[:app_identifier], params[:build_number])
|
207
|
+
upload_build_url = upload_urls['buildUrl']
|
208
|
+
self.upload_file(upload_build_url, params[:apk])
|
209
|
+
UI.success("Successfully uploaded apk file")
|
210
|
+
if params[:mapping]
|
211
|
+
upload_mapping_file_url = upload_urls['debugFileUrl']
|
212
|
+
self.upload_file(upload_mapping_file_url, params[:mapping])
|
213
|
+
UI.success("Successfully uploaded mapping file")
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
def self.upload_file(url, build)
|
219
|
+
client = S3::Client.new
|
220
|
+
client.upload_file(url, build)
|
221
|
+
end
|
222
|
+
|
177
223
|
def self.base_url(environment)
|
178
224
|
case environment
|
179
225
|
when :production
|
@@ -184,11 +230,6 @@ module Fastlane
|
|
184
230
|
end
|
185
231
|
private_class_method :base_url
|
186
232
|
|
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
233
|
def self.commit_author
|
193
234
|
sh("git --no-pager show -s --format='%ae'", print_command: false, print_command_output: false).strip
|
194
235
|
end
|
@@ -0,0 +1,30 @@
|
|
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
|
+
|
23
|
+
connection.put(
|
24
|
+
'',
|
25
|
+
File.read(file)
|
26
|
+
)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
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.3
|
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-10-31 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
|
@@ -265,8 +265,6 @@ files:
|
|
265
265
|
- lib/fastlane/plugin/polidea.rb
|
266
266
|
- lib/fastlane/plugin/polidea/actions/add_prefix_schema.rb
|
267
267
|
- lib/fastlane/plugin/polidea/actions/extract_app_info.rb
|
268
|
-
- lib/fastlane/plugin/polidea/actions/fota_mail.rb
|
269
|
-
- lib/fastlane/plugin/polidea/actions/fota_s3.rb
|
270
268
|
- lib/fastlane/plugin/polidea/actions/import_provisioning.rb
|
271
269
|
- lib/fastlane/plugin/polidea/actions/release_notes.rb
|
272
270
|
- lib/fastlane/plugin/polidea/actions/release_notes_from_commits.rb
|
@@ -275,6 +273,7 @@ files:
|
|
275
273
|
- lib/fastlane/plugin/polidea/helper/mime.rb
|
276
274
|
- lib/fastlane/plugin/polidea/helper/page_generator.rb
|
277
275
|
- lib/fastlane/plugin/polidea/helper/qr_generator.rb
|
276
|
+
- lib/fastlane/plugin/polidea/helper/s3.rb
|
278
277
|
- lib/fastlane/plugin/polidea/helper/shuttle.rb
|
279
278
|
- lib/fastlane/plugin/polidea/version.rb
|
280
279
|
- templates/install.erb
|
@@ -294,9 +293,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
294
293
|
version: '0'
|
295
294
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
296
295
|
requirements:
|
297
|
-
- - "
|
296
|
+
- - ">"
|
298
297
|
- !ruby/object:Gem::Version
|
299
|
-
version:
|
298
|
+
version: 1.3.1
|
300
299
|
requirements: []
|
301
300
|
rubygems_version: 3.0.1
|
302
301
|
signing_key:
|
@@ -1,187 +0,0 @@
|
|
1
|
-
require 'redcarpet'
|
2
|
-
require 'fastlane/erb_template_helper'
|
3
|
-
|
4
|
-
module Fastlane
|
5
|
-
module Actions
|
6
|
-
class FotaMailAction < Action
|
7
|
-
def self.is_supported?(platform)
|
8
|
-
true
|
9
|
-
end
|
10
|
-
|
11
|
-
def self.run(options)
|
12
|
-
Fastlane::Polidea.session.action_launched("fota_mail", options)
|
13
|
-
|
14
|
-
Actions.verify_gem!('premailer')
|
15
|
-
require 'premailer'
|
16
|
-
inline_images(options)
|
17
|
-
mailgunit(options)
|
18
|
-
|
19
|
-
Fastlane::Polidea.session.action_completed("fota_mail")
|
20
|
-
UI.success "Mail sent!"
|
21
|
-
end
|
22
|
-
|
23
|
-
def self.description
|
24
|
-
"Send a success/error message to an email group"
|
25
|
-
end
|
26
|
-
|
27
|
-
def self.available_options
|
28
|
-
[
|
29
|
-
FastlaneCore::ConfigItem.new(key: :postmaster,
|
30
|
-
env_name: "MAILGUN_SANDBOX_POSTMASTER",
|
31
|
-
description: "Mailgun sandbox domain postmaster for your mail"),
|
32
|
-
FastlaneCore::ConfigItem.new(key: :apikey,
|
33
|
-
env_name: "MAILGUN_APIKEY",
|
34
|
-
description: "Mailgun apikey for your mail"),
|
35
|
-
FastlaneCore::ConfigItem.new(key: :to,
|
36
|
-
env_name: "MAILGUN_TO",
|
37
|
-
description: "Destination of your mail"),
|
38
|
-
FastlaneCore::ConfigItem.new(key: :from,
|
39
|
-
env_name: "MAILGUN_FROM",
|
40
|
-
optional: true,
|
41
|
-
description: "Mailgun sender name",
|
42
|
-
default_value: "Polidea"),
|
43
|
-
FastlaneCore::ConfigItem.new(key: :success,
|
44
|
-
env_name: "MAILGUN_SUCCESS",
|
45
|
-
description: "Was this build successful? (true/false)",
|
46
|
-
optional: true,
|
47
|
-
default_value: true,
|
48
|
-
is_string: false),
|
49
|
-
FastlaneCore::ConfigItem.new(key: :ci_build_link,
|
50
|
-
env_name: "MAILGUN_CI_BUILD_LINK",
|
51
|
-
description: "CI Build Link",
|
52
|
-
optional: true,
|
53
|
-
is_string: true),
|
54
|
-
FastlaneCore::ConfigItem.new(key: :template_path,
|
55
|
-
env_name: "MAILGUN_TEMPLATE_PATH",
|
56
|
-
description: "Mail HTML template",
|
57
|
-
optional: true,
|
58
|
-
is_string: true),
|
59
|
-
FastlaneCore::ConfigItem.new(key: :platform,
|
60
|
-
env_name: "MAILGUN_PLATFORM",
|
61
|
-
description: "Platform used in mail template",
|
62
|
-
optional: true,
|
63
|
-
default_value: Actions.lane_context[Actions::SharedValues::PLATFORM_NAME]),
|
64
|
-
FastlaneCore::ConfigItem.new(key: :app_icon,
|
65
|
-
env_name: "MAILGUN_APP_ICON",
|
66
|
-
description: "Path to app icon file",
|
67
|
-
is_string: true,
|
68
|
-
optional: true,
|
69
|
-
default_value: Actions.lane_context[SharedValues::ICON_OUTPUT_PATH]),
|
70
|
-
FastlaneCore::ConfigItem.new(key: :app_name,
|
71
|
-
env_name: "MAILGUN_APP_NAME",
|
72
|
-
description: "Application name",
|
73
|
-
is_string: true,
|
74
|
-
default_value: Actions.lane_context[SharedValues::APP_NAME]),
|
75
|
-
FastlaneCore::ConfigItem.new(key: :app_version,
|
76
|
-
env_name: "MAILGUN_APP_VERSION",
|
77
|
-
description: "Application version",
|
78
|
-
is_string: true,
|
79
|
-
default_value: Actions.lane_context[SharedValues::APP_VERSION]),
|
80
|
-
FastlaneCore::ConfigItem.new(key: :build_number,
|
81
|
-
env_name: "MAILGUN_BUILD_NUMBER",
|
82
|
-
description: "Build number",
|
83
|
-
default_value: Actions.lane_context[SharedValues::BUILD_NUMBER]),
|
84
|
-
FastlaneCore::ConfigItem.new(key: :installation_link,
|
85
|
-
env_name: "MAILGUN_INSTALLATION_LINK",
|
86
|
-
description: "Link to installation page",
|
87
|
-
is_string: true,
|
88
|
-
default_value: Actions.lane_context[SharedValues::S3_HTML_OUTPUT_PATH]),
|
89
|
-
FastlaneCore::ConfigItem.new(key: :release_notes,
|
90
|
-
env_name: "MAILGUN_RELEASE_NOTES",
|
91
|
-
description: "Release notes",
|
92
|
-
type: String,
|
93
|
-
optional: true,
|
94
|
-
default_value: Actions.lane_context[SharedValues::RELEASE_NOTES]),
|
95
|
-
FastlaneCore::ConfigItem.new(key: :binary_size,
|
96
|
-
env_name: "MAILGUN_BINARY_SIZE",
|
97
|
-
description: "Binary size",
|
98
|
-
type: Integer,
|
99
|
-
default_value: Actions.lane_context[SharedValues::BINARY_SIZE]),
|
100
|
-
FastlaneCore::ConfigItem.new(key: :inline,
|
101
|
-
type: Array,
|
102
|
-
optional: true,
|
103
|
-
default_value: [])
|
104
|
-
]
|
105
|
-
end
|
106
|
-
|
107
|
-
def self.author
|
108
|
-
"thiagolioy"
|
109
|
-
end
|
110
|
-
|
111
|
-
def self.inline_images(options)
|
112
|
-
options[:inline] = [
|
113
|
-
qr_code(options[:installation_link])
|
114
|
-
]
|
115
|
-
options[:inline] << File.new(options[:app_icon]) if options[:app_icon]
|
116
|
-
end
|
117
|
-
|
118
|
-
def self.qr_code(installation_link)
|
119
|
-
qr_code_path = "/tmp/qr_code.png"
|
120
|
-
QRGenerator.new(installation_link, ::ChunkyPNG::Color.rgb(21, 18, 126)).generate(qr_code_path)
|
121
|
-
File.new(qr_code_path)
|
122
|
-
end
|
123
|
-
|
124
|
-
def self.mailgunit(options)
|
125
|
-
sandbox_domain = options[:postmaster].split("@").last
|
126
|
-
body = mail_template(options)
|
127
|
-
|
128
|
-
sh """curl -s --user 'api:#{options[:apikey]}' \
|
129
|
-
https://api.mailgun.net/v3/#{sandbox_domain}/messages \
|
130
|
-
-F from='#{options[:from]} <#{options[:postmaster]}>' \
|
131
|
-
-F to='#{options[:to]}' \
|
132
|
-
-F subject='#{options[:app_name]} #{options[:app_version]} (#{options[:build_number]}) for #{human_platform(options[:platform])} is ready to install' \
|
133
|
-
--form-string html=#{Shellwords.escape(body)} \ """ + options[:inline].map { |file| "-F inline=@#{file.path}" }.join(" "), print_command: false, print_command_output: false
|
134
|
-
|
135
|
-
return body
|
136
|
-
end
|
137
|
-
|
138
|
-
def self.mail_template(options)
|
139
|
-
hash = {
|
140
|
-
author: Actions.git_author_email,
|
141
|
-
last_commit: Actions.last_git_commit_message,
|
142
|
-
is_android: options[:platform] == :android,
|
143
|
-
app_icon: options[:app_icon] ? File.basename(options[:app_icon]) : nil,
|
144
|
-
app_name: options[:app_name],
|
145
|
-
app_version: options[:app_version],
|
146
|
-
build_number: options[:build_number],
|
147
|
-
installation_link: options[:installation_link],
|
148
|
-
release_notes: options[:release_notes],
|
149
|
-
platform: options[:platform],
|
150
|
-
release_date: DateTime.now.strftime('%b %d, %Y'),
|
151
|
-
binary_size: (options[:binary_size] / 1024.0 / 1024.0).round(2).to_s,
|
152
|
-
qr_code: "qr_code.png"
|
153
|
-
}
|
154
|
-
hash[:success] = options[:success]
|
155
|
-
hash[:ci_build_link] = options[:ci_build_link]
|
156
|
-
|
157
|
-
# create html from template
|
158
|
-
html_template_path = options[:template_path]
|
159
|
-
if html_template_path && File.exist?(html_template_path)
|
160
|
-
eth = Fastlane::ErbTemplateHelper
|
161
|
-
html_template = eth.load_from_path(html_template_path)
|
162
|
-
mail_html = eth.render(html_template, hash)
|
163
|
-
else
|
164
|
-
mail_html = PageGenerator.mail(hash)
|
165
|
-
end
|
166
|
-
|
167
|
-
premailer = Premailer.new(
|
168
|
-
mail_html,
|
169
|
-
{ warn_level: Premailer::Warnings::SAFE, with_html_string: true }
|
170
|
-
)
|
171
|
-
premailer.to_inline_css
|
172
|
-
end
|
173
|
-
|
174
|
-
def self.human_platform(platform)
|
175
|
-
case platform
|
176
|
-
when :ios
|
177
|
-
"iOS"
|
178
|
-
when :android
|
179
|
-
"Android"
|
180
|
-
else
|
181
|
-
platform.to_s
|
182
|
-
end
|
183
|
-
end
|
184
|
-
end
|
185
|
-
end
|
186
|
-
end
|
187
|
-
# rubocop:enable Metrics/MethodLength
|
@@ -1,568 +0,0 @@
|
|
1
|
-
# rubocop:disable Metrics/AbcSize
|
2
|
-
# rubocop:disable Metrics/ClassLength
|
3
|
-
require 'fastlane/erb_template_helper'
|
4
|
-
require 'ostruct'
|
5
|
-
require 'securerandom'
|
6
|
-
|
7
|
-
module Fastlane
|
8
|
-
module Actions
|
9
|
-
module SharedValues
|
10
|
-
S3_IPA_OUTPUT_PATH = :S3_IPA_OUTPUT_PATH
|
11
|
-
S3_DSYM_OUTPUT_PATH = :S3_DSYM_OUTPUT_PATH
|
12
|
-
S3_PLIST_OUTPUT_PATH = :S3_PLIST_OUTPUT_PATH
|
13
|
-
S3_APK_OUTPUT_PATH = :S3_APK_OUTPUT_PATH
|
14
|
-
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
|
-
end
|
19
|
-
|
20
|
-
class FotaS3Action < Action
|
21
|
-
def self.run(config)
|
22
|
-
Fastlane::Polidea.session.action_launched("fota_s3", config)
|
23
|
-
|
24
|
-
platform = Actions.lane_context[Actions::SharedValues::PLATFORM_NAME].to_sym
|
25
|
-
|
26
|
-
# Calling fetch on config so that default values will be used
|
27
|
-
params = {}
|
28
|
-
params[:ipa] = config[:ipa]
|
29
|
-
params[:apk] = config[:apk]
|
30
|
-
params[:icon] = config[:icon]
|
31
|
-
params[:dsym] = config[:dsym]
|
32
|
-
params[:mapping] = config[:mapping]
|
33
|
-
params[:access_key] = config[:access_key]
|
34
|
-
params[:secret_access_key] = config[:secret_access_key]
|
35
|
-
params[:bucket] = config[:bucket]
|
36
|
-
params[:region] = config[:region]
|
37
|
-
params[:acl] = config[:acl]
|
38
|
-
params[:upload_metadata] = config[:upload_metadata]
|
39
|
-
params[:plist_template_path] = config[:plist_template_path]
|
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]
|
47
|
-
|
48
|
-
case platform
|
49
|
-
when :ios
|
50
|
-
upload_ios(params)
|
51
|
-
when :android
|
52
|
-
upload_android(params)
|
53
|
-
end
|
54
|
-
|
55
|
-
Fastlane::Polidea.session.action_completed("fota_s3")
|
56
|
-
return true
|
57
|
-
end
|
58
|
-
|
59
|
-
def self.upload_ios(params)
|
60
|
-
# 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
|
-
ipa_file = params[:ipa]
|
67
|
-
icon_file = params[:icon]
|
68
|
-
dsym_file = params[:dsym]
|
69
|
-
acl = params[:acl]
|
70
|
-
release_notes = params[:release_notes]
|
71
|
-
treat_bucket_as_domain_name = params[:treat_bucket_as_domain_name]
|
72
|
-
|
73
|
-
validate(params)
|
74
|
-
UI.user_error!("No IPA file path given, pass using `ipa: 'ipa path'`") unless ipa_file.to_s.length > 0
|
75
|
-
|
76
|
-
UI.message("Will transform S3 urls from https://s3.amazonaws.com/#{s3_bucket} to https://#{s3_bucket}") if treat_bucket_as_domain_name
|
77
|
-
|
78
|
-
bucket = get_bucket(s3_access_key, s3_secret_access_key, s3_region, s3_bucket)
|
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)
|
100
|
-
|
101
|
-
# Setting action and environment variables
|
102
|
-
Actions.lane_context[SharedValues::S3_IPA_OUTPUT_PATH] = ipa_url
|
103
|
-
ENV[SharedValues::S3_IPA_OUTPUT_PATH.to_s] = ipa_url
|
104
|
-
|
105
|
-
if dsym_file
|
106
|
-
dsym_file_basename = File.basename(dsym_file)
|
107
|
-
dsym_file_name = "#{url_part}#{dsym_file_basename}"
|
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
|
117
|
-
end
|
118
|
-
|
119
|
-
#####################################
|
120
|
-
#
|
121
|
-
# html and plist building
|
122
|
-
#
|
123
|
-
#####################################
|
124
|
-
|
125
|
-
# Creating plist and html names
|
126
|
-
plist_file_name = "#{url_part}manifest.plist"
|
127
|
-
plist_url = "https://#{s3_subdomain}.amazonaws.com/#{s3_bucket}/#{plist_file_name}"
|
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]}'")
|
216
|
-
end
|
217
|
-
end
|
218
|
-
|
219
|
-
def self.upload_android(params)
|
220
|
-
# 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
|
-
apk_file = params[:apk]
|
226
|
-
icon_file = params[:icon]
|
227
|
-
mapping_file = params[:mapping]
|
228
|
-
acl = params[:acl]
|
229
|
-
release_notes = params[:release_notes]
|
230
|
-
treat_bucket_as_domain_name = params[:treat_bucket_as_domain_name]
|
231
|
-
|
232
|
-
validate(params)
|
233
|
-
UI.user_error!("No APK file path given, pass using `apk: 'apk path'`") unless apk_file.to_s.length > 0
|
234
|
-
|
235
|
-
UI.message("Will transform S3 urls from https://s3.amazonaws.com/#{s3_bucket} to https://#{s3_bucket}") if treat_bucket_as_domain_name
|
236
|
-
|
237
|
-
bucket = get_bucket(s3_access_key, s3_secret_access_key, s3_region, s3_bucket)
|
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)
|
254
|
-
|
255
|
-
# Setting action and environment variables
|
256
|
-
Actions.lane_context[SharedValues::S3_APK_OUTPUT_PATH] = apk_url
|
257
|
-
ENV[SharedValues::S3_APK_OUTPUT_PATH.to_s] = apk_url
|
258
|
-
|
259
|
-
if mapping_file
|
260
|
-
mapping_file_basename = File.basename(mapping_file)
|
261
|
-
mapping_file_name = "#{url_part}#{mapping_file_basename}"
|
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)
|
265
|
-
|
266
|
-
# Setting action and environment variables
|
267
|
-
Actions.lane_context[SharedValues::S3_MAPPING_OUTPUT_PATH] = mapping_url
|
268
|
-
ENV[SharedValues::S3_MAPPING_OUTPUT_PATH.to_s] = mapping_url
|
269
|
-
|
270
|
-
mapping_file_data.close
|
271
|
-
end
|
272
|
-
|
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)
|
300
|
-
|
301
|
-
Actions.lane_context[SharedValues::S3_HTML_OUTPUT_PATH] = html_url
|
302
|
-
ENV[SharedValues::S3_HTML_OUTPUT_PATH.to_s] = html_url
|
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]}'")
|
314
|
-
end
|
315
|
-
end
|
316
|
-
|
317
|
-
def self.validate(params)
|
318
|
-
s3_access_key = params[:access_key]
|
319
|
-
s3_secret_access_key = params[:secret_access_key]
|
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
|
325
|
-
end
|
326
|
-
|
327
|
-
def self.get_url_part(app_name, platform, app_version, build_number)
|
328
|
-
random_part = SecureRandom.hex(10)
|
329
|
-
"#{app_name}/#{platform}/#{app_version}_#{build_number}/#{random_part}/"
|
330
|
-
end
|
331
|
-
|
332
|
-
def self.get_bucket(s3_access_key, s3_secret_access_key, s3_region, s3_bucket)
|
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
|
429
|
-
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
|
-
end
|
446
|
-
|
447
|
-
def self.description
|
448
|
-
"Generates a plist file and uploads all to AWS S3"
|
449
|
-
end
|
450
|
-
|
451
|
-
def self.available_options
|
452
|
-
[
|
453
|
-
FastlaneCore::ConfigItem.new(key: :ipa,
|
454
|
-
env_name: "",
|
455
|
-
description: ".ipa file for the build",
|
456
|
-
optional: true,
|
457
|
-
default_value: Actions.lane_context[SharedValues::IPA_OUTPUT_PATH]),
|
458
|
-
FastlaneCore::ConfigItem.new(key: :dsym,
|
459
|
-
env_name: "",
|
460
|
-
description: "zipped .dsym package for the build",
|
461
|
-
optional: true,
|
462
|
-
default_value: Actions.lane_context[SharedValues::DSYM_OUTPUT_PATH]),
|
463
|
-
FastlaneCore::ConfigItem.new(key: :apk,
|
464
|
-
env_name: "",
|
465
|
-
description: ".apk file for the build",
|
466
|
-
optional: true,
|
467
|
-
default_value: Actions.lane_context[SharedValues::GRADLE_APK_OUTPUT_PATH]),
|
468
|
-
FastlaneCore::ConfigItem.new(key: :mapping,
|
469
|
-
env_name: "",
|
470
|
-
description: "The path to the mapping.txt file",
|
471
|
-
optional: true,
|
472
|
-
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
|
-
FastlaneCore::ConfigItem.new(key: :treat_bucket_as_domain_name,
|
536
|
-
description: "If it's true, it transforms all urls from https://s3.amazonaws.com/BUCKET_NAME to https://BUCKET_NAME",
|
537
|
-
is_string: false,
|
538
|
-
optional: true,
|
539
|
-
default_value: true)
|
540
|
-
]
|
541
|
-
end
|
542
|
-
|
543
|
-
def self.output
|
544
|
-
[
|
545
|
-
['S3_IPA_OUTPUT_PATH', 'Direct HTTP link to the uploaded ipa file'],
|
546
|
-
['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
|
-
['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']
|
553
|
-
]
|
554
|
-
end
|
555
|
-
|
556
|
-
def self.author
|
557
|
-
"joshdholtz"
|
558
|
-
end
|
559
|
-
|
560
|
-
def self.is_supported?(platform)
|
561
|
-
[:ios, :android].include? platform
|
562
|
-
end
|
563
|
-
end
|
564
|
-
end
|
565
|
-
end
|
566
|
-
# rubocop:enable Metrics/AbcSize
|
567
|
-
# rubocop:enable Metrics/MethodLength
|
568
|
-
# rubocop:enable Metrics/ClassLength
|