fastlane-plugin-firebase_app_distribution 0.2.5 → 0.5.0
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/fad-icon.png +0 -0
- data/lib/fastlane/plugin/firebase_app_distribution/actions/firebase_app_distribution_action.rb +143 -43
- data/lib/fastlane/plugin/firebase_app_distribution/actions/firebase_app_distribution_add_testers_action.rb +90 -0
- data/lib/fastlane/plugin/firebase_app_distribution/actions/firebase_app_distribution_get_latest_release.rb +114 -0
- data/lib/fastlane/plugin/firebase_app_distribution/actions/firebase_app_distribution_get_udids.rb +97 -0
- data/lib/fastlane/plugin/firebase_app_distribution/actions/firebase_app_distribution_remove_testers_action.rb +88 -0
- data/lib/fastlane/plugin/firebase_app_distribution/client/aab_info.rb +42 -0
- data/lib/fastlane/plugin/firebase_app_distribution/client/firebase_app_distribution_api_client.rb +223 -116
- data/lib/fastlane/plugin/firebase_app_distribution/helper/firebase_app_distribution_auth_client.rb +80 -34
- data/lib/fastlane/plugin/firebase_app_distribution/helper/firebase_app_distribution_error_message.rb +15 -5
- data/lib/fastlane/plugin/firebase_app_distribution/helper/firebase_app_distribution_helper.rb +26 -5
- data/lib/fastlane/plugin/firebase_app_distribution/helper/upload_status_response.rb +55 -15
- data/lib/fastlane/plugin/firebase_app_distribution/version.rb +1 -1
- metadata +9 -4
- data/lib/fastlane/plugin/firebase_app_distribution/actions/firebase_app_distribution_login.rb +0 -58
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 745bfb3dfc4c6c48f389c8e4d75b50026cf37e872ce26e7510aefef049280329
|
4
|
+
data.tar.gz: 8122801b30f95422216c9c5343d102bc6b11fbc16308f268515e7a3405bbf070
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6ac42a57fdbda601b6ef2656a7e0d1b38304f022a26c970a75f1e0a43d01f2607f993c5500bceaf8ffb5b24ada6fbcbcb1ccf84d7dc8d87dc7d62049561d7886
|
7
|
+
data.tar.gz: ae12197e0149e187b02716e28a71207cd5ce67d14ea331bb9c230e41a53237e1c3e4359b1178f09bf059ac2d9697cb4b667d358a1d4751a3b47006efcaf131bb
|
data/fad-icon.png
ADDED
Binary file
|
data/lib/fastlane/plugin/firebase_app_distribution/actions/firebase_app_distribution_action.rb
CHANGED
@@ -8,40 +8,93 @@ require_relative '../helper/firebase_app_distribution_error_message'
|
|
8
8
|
require_relative '../client/firebase_app_distribution_api_client'
|
9
9
|
require_relative '../helper/firebase_app_distribution_auth_client'
|
10
10
|
|
11
|
-
## TODO: should always use a file underneath? I think so.
|
12
11
|
## How should we document the usage of release notes?
|
13
12
|
module Fastlane
|
14
13
|
module Actions
|
15
|
-
|
16
|
-
|
14
|
+
module SharedValues
|
15
|
+
FIREBASE_APP_DISTRO_RELEASE ||= :FIREBASE_APP_DISTRO_RELEASE
|
16
|
+
end
|
17
17
|
|
18
|
+
class FirebaseAppDistributionAction < Action
|
18
19
|
extend Auth::FirebaseAppDistributionAuthClient
|
19
20
|
extend Helper::FirebaseAppDistributionHelper
|
20
21
|
|
22
|
+
DEFAULT_UPLOAD_TIMEOUT_SECONDS = 300
|
23
|
+
|
21
24
|
def self.run(params)
|
22
|
-
params.values # to validate all inputs before looking for the ipa/apk
|
25
|
+
params.values # to validate all inputs before looking for the ipa/apk/aab
|
26
|
+
|
27
|
+
if params[:debug]
|
28
|
+
UI.important("Warning: Debug logging enabled. Output may include sensitive information.")
|
29
|
+
end
|
23
30
|
|
24
31
|
app_id = app_id_from_params(params)
|
32
|
+
app_name = app_name_from_app_id(app_id)
|
25
33
|
platform = lane_platform || platform_from_app_id(app_id)
|
26
|
-
binary_path = binary_path_from_platform(platform, params[:ipa_path], params[:apk_path])
|
27
34
|
|
28
|
-
|
29
|
-
|
35
|
+
binary_path = get_binary_path(platform, params)
|
36
|
+
UI.user_error!("Couldn't find binary") if binary_path.nil?
|
37
|
+
UI.user_error!("Couldn't find binary at path #{binary_path}") unless File.exist?(binary_path)
|
38
|
+
binary_type = binary_type_from_path(binary_path)
|
39
|
+
|
40
|
+
auth_token = fetch_auth_token(
|
41
|
+
params[:service_credentials_file], params[:firebase_cli_token], params[:debug]
|
42
|
+
)
|
43
|
+
fad_api_client = Client::FirebaseAppDistributionApiClient.new(auth_token, params[:debug])
|
44
|
+
|
45
|
+
# If binary is an AAB, get the AAB info for this app, which includes the integration state and certificate data
|
46
|
+
if binary_type == :AAB
|
47
|
+
aab_info = fad_api_client.get_aab_info(app_name)
|
48
|
+
validate_aab_setup!(aab_info)
|
49
|
+
end
|
50
|
+
|
51
|
+
upload_timeout = get_upload_timeout(params)
|
52
|
+
|
53
|
+
upload_status_response = fad_api_client.upload(app_name, binary_path, platform.to_s, upload_timeout)
|
54
|
+
release_name = upload_status_response.release_name
|
55
|
+
release = upload_status_response.release
|
30
56
|
|
31
|
-
|
32
|
-
|
33
|
-
|
57
|
+
if binary_type == :AAB && aab_info && !aab_info.certs_provided?
|
58
|
+
updated_aab_info = fad_api_client.get_aab_info(app_name)
|
59
|
+
if updated_aab_info.certs_provided?
|
60
|
+
UI.message("After you upload an AAB for the first time, App Distribution " \
|
61
|
+
"generates a new test certificate. All AAB uploads are re-signed with this test " \
|
62
|
+
"certificate. Use the certificate fingerprints below to register your app " \
|
63
|
+
"signing key with API providers, such as Google Sign-In and Google Maps.\n" \
|
64
|
+
"MD-1 certificate fingerprint: #{updated_aab_info.md5_certificate_hash}\n" \
|
65
|
+
"SHA-1 certificate fingerprint: #{updated_aab_info.sha1_certificate_hash}\n" \
|
66
|
+
"SHA-256 certificate fingerprint: #{updated_aab_info.sha256_certificate_hash}")
|
67
|
+
end
|
34
68
|
end
|
35
69
|
|
36
|
-
release_notes =
|
37
|
-
|
70
|
+
release_notes = release_notes(params)
|
71
|
+
if release_notes.nil? || release_notes.empty?
|
72
|
+
UI.message("⏩ No release notes passed in. Skipping this step.")
|
73
|
+
else
|
74
|
+
release = fad_api_client.update_release_notes(release_name, release_notes)
|
75
|
+
end
|
38
76
|
|
39
77
|
testers = get_value_from_value_or_file(params[:testers], params[:testers_file])
|
40
78
|
groups = get_value_from_value_or_file(params[:groups], params[:groups_file])
|
41
79
|
emails = string_to_array(testers)
|
42
|
-
|
43
|
-
fad_api_client.
|
44
|
-
UI.success("🎉 App Distribution upload finished successfully.")
|
80
|
+
group_aliases = string_to_array(groups)
|
81
|
+
fad_api_client.distribute(release_name, emails, group_aliases)
|
82
|
+
UI.success("🎉 App Distribution upload finished successfully. Setting Actions.lane_context[SharedValues::FIREBASE_APP_DISTRO_RELEASE] to the uploaded release.")
|
83
|
+
|
84
|
+
if upload_status_response.firebase_console_uri
|
85
|
+
UI.message("🔗 View this release in the Firebase console: #{upload_status_response.firebase_console_uri}")
|
86
|
+
end
|
87
|
+
|
88
|
+
if upload_status_response.testing_uri
|
89
|
+
UI.message("🔗 Share this release with testers who have access: #{upload_status_response.testing_uri}")
|
90
|
+
end
|
91
|
+
|
92
|
+
if upload_status_response.binary_download_uri
|
93
|
+
UI.message("🔗 Download the release binary (link expires in 1 hour): #{upload_status_response.binary_download_uri}")
|
94
|
+
end
|
95
|
+
|
96
|
+
Actions.lane_context[SharedValues::FIREBASE_APP_DISTRO_RELEASE] = release
|
97
|
+
release
|
45
98
|
end
|
46
99
|
|
47
100
|
def self.description
|
@@ -90,37 +143,66 @@ module Fastlane
|
|
90
143
|
end
|
91
144
|
end
|
92
145
|
|
93
|
-
def self.
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
146
|
+
def self.get_binary_path(platform, params)
|
147
|
+
if platform == :ios
|
148
|
+
return params[:ipa_path] ||
|
149
|
+
Actions.lane_context[SharedValues::IPA_OUTPUT_PATH] ||
|
150
|
+
Dir["*.ipa"].sort_by { |x| File.mtime(x) }.last
|
151
|
+
end
|
152
|
+
|
153
|
+
if platform == :android
|
154
|
+
return params[:apk_path] || params[:android_artifact_path] if params[:apk_path] || params[:android_artifact_path]
|
155
|
+
|
156
|
+
if params[:android_artifact_type] == 'AAB'
|
157
|
+
return Actions.lane_context[SharedValues::GRADLE_AAB_OUTPUT_PATH] ||
|
158
|
+
Dir["*.aab"].last ||
|
159
|
+
Dir[File.join("app", "build", "outputs", "bundle", "release", "app-release.aab")].last
|
160
|
+
end
|
161
|
+
|
162
|
+
return Actions.lane_context[SharedValues::GRADLE_APK_OUTPUT_PATH] ||
|
163
|
+
Dir["*.apk"].last ||
|
164
|
+
Dir[File.join("app", "build", "outputs", "apk", "release", "app-release.apk")].last
|
101
165
|
end
|
102
166
|
end
|
103
167
|
|
104
|
-
def self.
|
105
|
-
if
|
106
|
-
|
168
|
+
def self.get_upload_timeout(params)
|
169
|
+
if params[:upload_timeout]
|
170
|
+
return params[:upload_timeout]
|
171
|
+
else
|
172
|
+
return DEFAULT_UPLOAD_TIMEOUT_SECONDS
|
107
173
|
end
|
174
|
+
end
|
108
175
|
|
109
|
-
|
110
|
-
|
176
|
+
def self.validate_aab_setup!(aab_info)
|
177
|
+
if aab_info && aab_info.integration_state != AabInfo::AabState::INTEGRATED && aab_info.integration_state != AabInfo::AabState::UNAVAILABLE
|
178
|
+
case aab_info.integration_state
|
179
|
+
when AabInfo::AabState::PLAY_ACCOUNT_NOT_LINKED
|
180
|
+
UI.user_error!(ErrorMessage::PLAY_ACCOUNT_NOT_LINKED)
|
181
|
+
when AabInfo::AabState::APP_NOT_PUBLISHED
|
182
|
+
UI.user_error!(ErrorMessage::APP_NOT_PUBLISHED)
|
183
|
+
when AabInfo::AabState::NO_APP_WITH_GIVEN_BUNDLE_ID_IN_PLAY_ACCOUNT
|
184
|
+
UI.user_error!(ErrorMessage::NO_APP_WITH_GIVEN_BUNDLE_ID_IN_PLAY_ACCOUNT)
|
185
|
+
when AabInfo::AabState::PLAY_IAS_TERMS_NOT_ACCEPTED
|
186
|
+
UI.user_error!(ErrorMessage::PLAY_IAS_TERMS_NOT_ACCEPTED)
|
187
|
+
else
|
188
|
+
UI.user_error!(ErrorMessage.aab_upload_error(aab_info.integration_state))
|
189
|
+
end
|
111
190
|
end
|
191
|
+
end
|
192
|
+
|
193
|
+
def self.release_notes(params)
|
194
|
+
release_notes_param =
|
195
|
+
get_value_from_value_or_file(params[:release_notes], params[:release_notes_file])
|
196
|
+
release_notes_param || Actions.lane_context[SharedValues::FL_CHANGELOG]
|
197
|
+
end
|
112
198
|
|
199
|
+
def self.available_options
|
113
200
|
[
|
114
201
|
# iOS Specific
|
115
202
|
FastlaneCore::ConfigItem.new(key: :ipa_path,
|
116
203
|
env_name: "FIREBASEAPPDISTRO_IPA_PATH",
|
117
204
|
description: "Path to your IPA file. Optional if you use the _gym_ or _xcodebuild_ action",
|
118
|
-
|
119
|
-
default_value_dynamic: true,
|
120
|
-
optional: true,
|
121
|
-
verify_block: proc do |value|
|
122
|
-
UI.user_error!("firebase_app_distribution: Couldn't find ipa file at path '#{value}'") unless File.exist?(value)
|
123
|
-
end),
|
205
|
+
optional: true),
|
124
206
|
FastlaneCore::ConfigItem.new(key: :googleservice_info_plist_path,
|
125
207
|
env_name: "GOOGLESERVICE_INFO_PLIST_PATH",
|
126
208
|
description: "Path to your GoogleService-Info.plist file, relative to the archived product path",
|
@@ -131,12 +213,21 @@ module Fastlane
|
|
131
213
|
FastlaneCore::ConfigItem.new(key: :apk_path,
|
132
214
|
env_name: "FIREBASEAPPDISTRO_APK_PATH",
|
133
215
|
description: "Path to your APK file",
|
134
|
-
|
216
|
+
optional: true),
|
217
|
+
FastlaneCore::ConfigItem.new(key: :android_artifact_path,
|
218
|
+
env_name: "FIREBASEAPPDISTRO_ANDROID_ARTIFACT_PATH",
|
219
|
+
description: "Path to your APK or AAB file",
|
220
|
+
optional: true),
|
221
|
+
FastlaneCore::ConfigItem.new(key: :android_artifact_type,
|
222
|
+
env_name: "FIREBASEAPPDISTRO_ANDROID_ARTIFACT_TYPE",
|
223
|
+
description: "Android artifact type. Set to 'APK' or 'AAB'. Defaults to 'APK' if not set",
|
224
|
+
default_value: "APK",
|
135
225
|
default_value_dynamic: true,
|
136
226
|
optional: true,
|
137
227
|
verify_block: proc do |value|
|
138
|
-
UI.user_error!("firebase_app_distribution:
|
228
|
+
UI.user_error!("firebase_app_distribution: '#{value}' is not a valid value for android_artifact_type. Should be 'APK' or 'AAB'") unless ['APK', 'AAB'].include?(value)
|
139
229
|
end),
|
230
|
+
# Generic
|
140
231
|
FastlaneCore::ConfigItem.new(key: :app,
|
141
232
|
env_name: "FIREBASEAPPDISTRO_APP",
|
142
233
|
description: "Your app's Firebase App ID. You can find the App ID in the Firebase console, on the General Settings page",
|
@@ -149,12 +240,12 @@ module Fastlane
|
|
149
240
|
type: String),
|
150
241
|
FastlaneCore::ConfigItem.new(key: :groups,
|
151
242
|
env_name: "FIREBASEAPPDISTRO_GROUPS",
|
152
|
-
description: "The
|
243
|
+
description: "The group aliases used for distribution, separated by commas",
|
153
244
|
optional: true,
|
154
245
|
type: String),
|
155
246
|
FastlaneCore::ConfigItem.new(key: :groups_file,
|
156
247
|
env_name: "FIREBASEAPPDISTRO_GROUPS_FILE",
|
157
|
-
description: "The
|
248
|
+
description: "The group aliases used for distribution, separated by commas",
|
158
249
|
optional: true,
|
159
250
|
type: String),
|
160
251
|
FastlaneCore::ConfigItem.new(key: :testers,
|
@@ -170,8 +261,6 @@ module Fastlane
|
|
170
261
|
FastlaneCore::ConfigItem.new(key: :release_notes,
|
171
262
|
env_name: "FIREBASEAPPDISTRO_RELEASE_NOTES",
|
172
263
|
description: "Release notes for this build",
|
173
|
-
default_value: Actions.lane_context[SharedValues::FL_CHANGELOG],
|
174
|
-
default_value_dynamic: true,
|
175
264
|
optional: true,
|
176
265
|
type: String),
|
177
266
|
FastlaneCore::ConfigItem.new(key: :release_notes_file,
|
@@ -180,7 +269,7 @@ module Fastlane
|
|
180
269
|
optional: true,
|
181
270
|
type: String),
|
182
271
|
FastlaneCore::ConfigItem.new(key: :firebase_cli_token,
|
183
|
-
description: "Auth token
|
272
|
+
description: "Auth token generated using the Firebase CLI's login:ci command",
|
184
273
|
optional: true,
|
185
274
|
type: String),
|
186
275
|
FastlaneCore::ConfigItem.new(key: :debug,
|
@@ -191,7 +280,12 @@ module Fastlane
|
|
191
280
|
FastlaneCore::ConfigItem.new(key: :service_credentials_file,
|
192
281
|
description: "Path to Google service account json",
|
193
282
|
optional: true,
|
194
|
-
type: String)
|
283
|
+
type: String),
|
284
|
+
FastlaneCore::ConfigItem.new(key: :upload_timeout,
|
285
|
+
description: "The amount of seconds before the upload will timeout, if not completed",
|
286
|
+
optional: true,
|
287
|
+
default_value: DEFAULT_UPLOAD_TIMEOUT_SECONDS,
|
288
|
+
type: Integer)
|
195
289
|
]
|
196
290
|
end
|
197
291
|
|
@@ -207,12 +301,18 @@ module Fastlane
|
|
207
301
|
[
|
208
302
|
<<-CODE
|
209
303
|
firebase_app_distribution(
|
210
|
-
app: "
|
304
|
+
app: "<your Firebase app ID>",
|
211
305
|
testers: "snatchev@google.com, rebeccahe@google.com"
|
212
306
|
)
|
213
307
|
CODE
|
214
308
|
]
|
215
309
|
end
|
310
|
+
|
311
|
+
def self.output
|
312
|
+
[
|
313
|
+
['FIREBASE_APP_DISTRO_RELEASE', 'A hash representing the uploaded release created in Firebase App Distribution']
|
314
|
+
]
|
315
|
+
end
|
216
316
|
end
|
217
317
|
end
|
218
318
|
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'fastlane/action'
|
2
|
+
require 'fastlane_core/ui/ui'
|
3
|
+
|
4
|
+
require_relative '../helper/firebase_app_distribution_helper'
|
5
|
+
require_relative '../helper/firebase_app_distribution_auth_client'
|
6
|
+
|
7
|
+
module Fastlane
|
8
|
+
module Actions
|
9
|
+
class FirebaseAppDistributionAddTestersAction < Action
|
10
|
+
extend Auth::FirebaseAppDistributionAuthClient
|
11
|
+
extend Helper::FirebaseAppDistributionHelper
|
12
|
+
|
13
|
+
def self.run(params)
|
14
|
+
auth_token = fetch_auth_token(params[:service_credentials_file], params[:firebase_cli_token])
|
15
|
+
fad_api_client = Client::FirebaseAppDistributionApiClient.new(auth_token, params[:debug])
|
16
|
+
|
17
|
+
if blank?(params[:emails]) && blank?(params[:file])
|
18
|
+
UI.user_error!("Must specify `emails` or `file`.")
|
19
|
+
end
|
20
|
+
|
21
|
+
emails = string_to_array(get_value_from_value_or_file(params[:emails], params[:file]))
|
22
|
+
|
23
|
+
UI.user_error!("Must pass at least one email") if blank?(emails)
|
24
|
+
|
25
|
+
if emails.count > 1000
|
26
|
+
UI.user_error!("A maximum of 1000 testers can be added at a time.")
|
27
|
+
end
|
28
|
+
|
29
|
+
UI.message("⏳ Adding #{emails.count} testers to project #{params[:project_number]}...")
|
30
|
+
|
31
|
+
fad_api_client.add_testers(params[:project_number], emails)
|
32
|
+
|
33
|
+
# The add_testers response lists all the testers from the request
|
34
|
+
# regardless of whether or not they were created or if they already
|
35
|
+
# exists so can't get an accurate count of the number of newly created testers
|
36
|
+
UI.success("✅ Tester(s) successfully added.")
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.description
|
40
|
+
"Create testers in bulk from a comma-separated list or a file"
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.authors
|
44
|
+
["Tunde Agboola"]
|
45
|
+
end
|
46
|
+
|
47
|
+
# supports markdown.
|
48
|
+
def self.details
|
49
|
+
"Create testers in bulk from a comma-separated list or a file"
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.available_options
|
53
|
+
[
|
54
|
+
FastlaneCore::ConfigItem.new(key: :project_number,
|
55
|
+
env_name: "FIREBASEAPPDISTRO_PROJECT_NUMBER",
|
56
|
+
description: "Your Firebase project number. You can find the project number in the Firebase console, on the General Settings page",
|
57
|
+
type: Integer,
|
58
|
+
optional: false),
|
59
|
+
FastlaneCore::ConfigItem.new(key: :emails,
|
60
|
+
env_name: "FIREBASEAPPDISTRO_ADD_TESTERS_EMAILS",
|
61
|
+
description: "Comma separated list of tester emails to be created. A maximum of 1000 testers can be created at a time",
|
62
|
+
optional: true,
|
63
|
+
type: String),
|
64
|
+
FastlaneCore::ConfigItem.new(key: :file,
|
65
|
+
env_name: "FIREBASEAPPDISTRO_ADD_TESTERS_FILE",
|
66
|
+
description: "Path to a file containing a comma separated list of tester emails to be created. A maximum of 1000 testers can be deleted at a time",
|
67
|
+
optional: true,
|
68
|
+
type: String),
|
69
|
+
FastlaneCore::ConfigItem.new(key: :service_credentials_file,
|
70
|
+
description: "Path to Google service credentials file",
|
71
|
+
optional: true,
|
72
|
+
type: String),
|
73
|
+
FastlaneCore::ConfigItem.new(key: :firebase_cli_token,
|
74
|
+
description: "Auth token generated using the Firebase CLI's login:ci command",
|
75
|
+
optional: true,
|
76
|
+
type: String),
|
77
|
+
FastlaneCore::ConfigItem.new(key: :debug,
|
78
|
+
description: "Print verbose debug output",
|
79
|
+
optional: true,
|
80
|
+
default_value: false,
|
81
|
+
is_string: false)
|
82
|
+
]
|
83
|
+
end
|
84
|
+
|
85
|
+
def self.is_supported?(platform)
|
86
|
+
true
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
require 'fastlane/action'
|
2
|
+
require_relative '../client/firebase_app_distribution_api_client'
|
3
|
+
require_relative '../helper/firebase_app_distribution_auth_client'
|
4
|
+
require_relative '../helper/firebase_app_distribution_helper'
|
5
|
+
|
6
|
+
module Fastlane
|
7
|
+
module Actions
|
8
|
+
module SharedValues
|
9
|
+
FIREBASE_APP_DISTRO_LATEST_RELEASE ||= :FIREBASE_APP_DISTRO_LATEST_RELEASE
|
10
|
+
end
|
11
|
+
class FirebaseAppDistributionGetLatestReleaseAction < Action
|
12
|
+
extend Auth::FirebaseAppDistributionAuthClient
|
13
|
+
extend Helper::FirebaseAppDistributionHelper
|
14
|
+
|
15
|
+
def self.run(params)
|
16
|
+
auth_token = fetch_auth_token(params[:service_credentials_file], params[:firebase_cli_token])
|
17
|
+
fad_api_client = Client::FirebaseAppDistributionApiClient.new(auth_token, params[:debug])
|
18
|
+
|
19
|
+
UI.message("⏳ Fetching latest release for app #{params[:app]}...")
|
20
|
+
|
21
|
+
releases = fad_api_client.list_releases(app_name_from_app_id(params[:app]), 1)[:releases] || []
|
22
|
+
if releases.empty?
|
23
|
+
latest_release = nil
|
24
|
+
UI.important("No releases for app #{params[:app]} found in App Distribution. Returning nil and setting Actions.lane_context[SharedValues::FIREBASE_APP_DISTRO_LATEST_RELEASE].")
|
25
|
+
else
|
26
|
+
latest_release = releases[0]
|
27
|
+
UI.success("✅ Latest release fetched successfully. Returning release and setting Actions.lane_context[SharedValues::FIREBASE_APP_DISTRO_LATEST_RELEASE].")
|
28
|
+
end
|
29
|
+
Actions.lane_context[SharedValues::FIREBASE_APP_DISTRO_LATEST_RELEASE] = latest_release
|
30
|
+
return latest_release
|
31
|
+
end
|
32
|
+
|
33
|
+
#####################################################
|
34
|
+
# @!group Documentation
|
35
|
+
#####################################################
|
36
|
+
|
37
|
+
def self.description
|
38
|
+
"Fetches the latest release in Firebase App Distribution"
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.details
|
42
|
+
[
|
43
|
+
"Fetches information about the most recently created release in App Distribution, including the version and release notes. Returns nil if no releases are found."
|
44
|
+
].join("\n")
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.available_options
|
48
|
+
[
|
49
|
+
FastlaneCore::ConfigItem.new(key: :app,
|
50
|
+
env_name: "FIREBASEAPPDISTRO_APP",
|
51
|
+
description: "Your app's Firebase App ID. You can find the App ID in the Firebase console, on the General Settings page",
|
52
|
+
optional: false,
|
53
|
+
type: String),
|
54
|
+
FastlaneCore::ConfigItem.new(key: :firebase_cli_token,
|
55
|
+
description: "Auth token generated using Firebase CLI's login:ci command",
|
56
|
+
optional: true,
|
57
|
+
type: String),
|
58
|
+
FastlaneCore::ConfigItem.new(key: :service_credentials_file,
|
59
|
+
description: "Path to Google service account json",
|
60
|
+
optional: true,
|
61
|
+
type: String),
|
62
|
+
FastlaneCore::ConfigItem.new(key: :debug,
|
63
|
+
description: "Print verbose debug output",
|
64
|
+
optional: true,
|
65
|
+
default_value: false,
|
66
|
+
is_string: false)
|
67
|
+
]
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.output
|
71
|
+
[
|
72
|
+
['FIREBASE_APP_DISTRO_LATEST_RELEASE', 'A hash representing the lastest release created in Firebase App Distribution']
|
73
|
+
]
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.return_value
|
77
|
+
"Hash representation of the lastest release created in Firebase App Distribution (see https://firebase.google.com/docs/reference/app-distribution/rest/v1/projects.apps.releases#resource:-release)"
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.return_type
|
81
|
+
:hash
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.authors
|
85
|
+
["lkellogg@google.com"]
|
86
|
+
end
|
87
|
+
|
88
|
+
def self.is_supported?(platform)
|
89
|
+
true
|
90
|
+
end
|
91
|
+
|
92
|
+
def self.example_code
|
93
|
+
[
|
94
|
+
'release = firebase_app_distribution_get_latest_release(app: "<your Firebase app ID>")',
|
95
|
+
'increment_build_number({
|
96
|
+
build_number: firebase_app_distribution_get_latest_release(app: "<your Firebase app ID>")[:buildVersion].to_i + 1
|
97
|
+
})'
|
98
|
+
]
|
99
|
+
end
|
100
|
+
|
101
|
+
def self.sample_return_value
|
102
|
+
{
|
103
|
+
name: "projects/123456789/apps/1:1234567890:ios:0a1b2c3d4e5f67890/releases/0a1b2c3d4",
|
104
|
+
releaseNotes: {
|
105
|
+
text: "Here are some release notes!"
|
106
|
+
},
|
107
|
+
displayVersion: "1.2.3",
|
108
|
+
buildVersion: "10",
|
109
|
+
createTime: "2021-10-06T15:01:23Z"
|
110
|
+
}
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
data/lib/fastlane/plugin/firebase_app_distribution/actions/firebase_app_distribution_get_udids.rb
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'fastlane/action'
|
2
|
+
require 'open3'
|
3
|
+
require 'shellwords'
|
4
|
+
require 'googleauth'
|
5
|
+
require_relative '../helper/firebase_app_distribution_helper'
|
6
|
+
require_relative '../helper/firebase_app_distribution_error_message'
|
7
|
+
require_relative '../client/firebase_app_distribution_api_client'
|
8
|
+
require_relative '../helper/firebase_app_distribution_auth_client'
|
9
|
+
|
10
|
+
module Fastlane
|
11
|
+
module Actions
|
12
|
+
class FirebaseAppDistributionGetUdidsAction < Action
|
13
|
+
extend Auth::FirebaseAppDistributionAuthClient
|
14
|
+
extend Helper::FirebaseAppDistributionHelper
|
15
|
+
|
16
|
+
def self.run(params)
|
17
|
+
auth_token = fetch_auth_token(params[:service_credentials_file], params[:firebase_cli_token])
|
18
|
+
fad_api_client = Client::FirebaseAppDistributionApiClient.new(auth_token, params[:debug])
|
19
|
+
|
20
|
+
app_id = params[:app]
|
21
|
+
udids = fad_api_client.get_udids(app_id)
|
22
|
+
|
23
|
+
if udids.empty?
|
24
|
+
UI.important("App Distribution fetched 0 tester UDIDs. Nothing written to output file.")
|
25
|
+
else
|
26
|
+
write_udids_to_file(udids, params[:output_file])
|
27
|
+
UI.success("🎉 App Distribution tester UDIDs written to: #{params[:output_file]}")
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.write_udids_to_file(udids, output_file)
|
32
|
+
File.open(output_file, 'w') do |f|
|
33
|
+
f.write("Device ID\tDevice Name\tDevice Platform\n")
|
34
|
+
udids.each do |tester_udid|
|
35
|
+
f.write("#{tester_udid[:udid]}\t#{tester_udid[:name]}\t#{tester_udid[:platform]}\n")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.description
|
41
|
+
"Download the UDIDs of your Firebase App Distribution testers"
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.authors
|
45
|
+
["Lee Kellogg"]
|
46
|
+
end
|
47
|
+
|
48
|
+
# supports markdown.
|
49
|
+
def self.details
|
50
|
+
"Export your testers' device identifiers in a CSV file, so you can add them your provisioning profile. This file can be imported into your Apple developer account using the Register Multiple Devices option. See the [App Distribution docs](https://firebase.google.com/docs/app-distribution/ios/distribute-console#register-tester-devices) for more info."
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.available_options
|
54
|
+
[
|
55
|
+
FastlaneCore::ConfigItem.new(key: :app,
|
56
|
+
env_name: "FIREBASEAPPDISTRO_APP",
|
57
|
+
description: "Your app's Firebase App ID. You can find the App ID in the Firebase console, on the General Settings page",
|
58
|
+
optional: false,
|
59
|
+
type: String),
|
60
|
+
FastlaneCore::ConfigItem.new(key: :output_file,
|
61
|
+
env_name: "FIREBASEAPPDISTRO_OUTPUT_FILE",
|
62
|
+
description: "The path to the file where the tester UDIDs will be written",
|
63
|
+
optional: false,
|
64
|
+
type: String),
|
65
|
+
FastlaneCore::ConfigItem.new(key: :firebase_cli_token,
|
66
|
+
description: "Auth token generated using the Firebase CLI's login:ci command",
|
67
|
+
optional: true,
|
68
|
+
type: String),
|
69
|
+
FastlaneCore::ConfigItem.new(key: :service_credentials_file,
|
70
|
+
description: "Path to Google service account json",
|
71
|
+
optional: true,
|
72
|
+
type: String),
|
73
|
+
FastlaneCore::ConfigItem.new(key: :debug,
|
74
|
+
description: "Print verbose debug output",
|
75
|
+
optional: true,
|
76
|
+
default_value: false,
|
77
|
+
is_string: false)
|
78
|
+
]
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.is_supported?(platform)
|
82
|
+
[:ios].include?(platform)
|
83
|
+
end
|
84
|
+
|
85
|
+
def self.example_code
|
86
|
+
[
|
87
|
+
<<-CODE
|
88
|
+
firebase_app_distribution_get_udids(
|
89
|
+
app: "<your Firebase app ID>",
|
90
|
+
output_file: "tester_udids.txt",
|
91
|
+
)
|
92
|
+
CODE
|
93
|
+
]
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|