fastlane-plugin-firebase_app_distribution 0.6.1 → 0.7.0.pre.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (17) hide show
  1. checksums.yaml +4 -4
  2. data/lib/fastlane/plugin/firebase_app_distribution/actions/firebase_app_distribution_action.rb +150 -40
  3. data/lib/fastlane/plugin/firebase_app_distribution/actions/firebase_app_distribution_add_testers_action.rb +52 -9
  4. data/lib/fastlane/plugin/firebase_app_distribution/actions/firebase_app_distribution_create_group_action.rb +25 -4
  5. data/lib/fastlane/plugin/firebase_app_distribution/actions/firebase_app_distribution_delete_group_action.rb +11 -3
  6. data/lib/fastlane/plugin/firebase_app_distribution/actions/firebase_app_distribution_get_latest_release.rb +39 -6
  7. data/lib/fastlane/plugin/firebase_app_distribution/actions/firebase_app_distribution_get_udids.rb +2 -2
  8. data/lib/fastlane/plugin/firebase_app_distribution/actions/firebase_app_distribution_remove_testers_action.rb +48 -9
  9. data/lib/fastlane/plugin/firebase_app_distribution/client/firebase_app_distribution_api_client.rb +1 -396
  10. data/lib/fastlane/plugin/firebase_app_distribution/helper/firebase_app_distribution_auth_client.rb +24 -19
  11. data/lib/fastlane/plugin/firebase_app_distribution/helper/firebase_app_distribution_error_message.rb +2 -3
  12. data/lib/fastlane/plugin/firebase_app_distribution/helper/firebase_app_distribution_helper.rb +31 -2
  13. data/lib/fastlane/plugin/firebase_app_distribution/version.rb +1 -1
  14. metadata +32 -7
  15. data/lib/fastlane/plugin/firebase_app_distribution/client/aab_info.rb +0 -42
  16. data/lib/fastlane/plugin/firebase_app_distribution/client/error_response.rb +0 -16
  17. data/lib/fastlane/plugin/firebase_app_distribution/helper/upload_status_response.rb +0 -77
@@ -1,6 +1,4 @@
1
1
  require 'fastlane_core/ui/ui'
2
- require_relative '../client/error_response'
3
- require_relative '../client/aab_info'
4
2
  require_relative '../helper/firebase_app_distribution_helper'
5
3
 
6
4
  module Fastlane
@@ -9,14 +7,8 @@ module Fastlane
9
7
  include Helper::FirebaseAppDistributionHelper
10
8
 
11
9
  BASE_URL = "https://firebaseappdistribution.googleapis.com"
12
- TOKEN_CREDENTIAL_URI = "https://oauth2.googleapis.com/token"
13
- MAX_POLLING_RETRIES = 60
14
- POLLING_INTERVAL_SECONDS = 5
15
10
 
16
11
  AUTHORIZATION = "Authorization"
17
- CONTENT_TYPE = "Content-Type"
18
- APPLICATION_JSON = "application/json"
19
- APPLICATION_OCTET_STREAM = "application/octet-stream"
20
12
  CLIENT_VERSION = "X-Client-Version"
21
13
 
22
14
  def initialize(auth_token, debug = false)
@@ -24,169 +16,6 @@ module Fastlane
24
16
  @debug = debug
25
17
  end
26
18
 
27
- # Enables tester access to the specified app release. Skips this
28
- # step if no testers are passed in (emails and group_aliases are nil/empty).
29
- #
30
- # args
31
- # release_name - App release resource name, returned by upload_status endpoint
32
- # emails - String array of app testers' email addresses
33
- # group_aliases - String array of Firebase tester group aliases
34
- #
35
- # Throws a user_error if emails or group_aliases are invalid
36
- def distribute(release_name, emails, group_aliases)
37
- if (emails.nil? || emails.empty?) && (group_aliases.nil? || group_aliases.empty?)
38
- UI.success("✅ No testers passed in. Skipping this step.")
39
- return
40
- end
41
- payload = { testerEmails: emails, groupAliases: group_aliases }
42
- begin
43
- connection.post(distribute_url(release_name), payload.to_json) do |request|
44
- request.headers[AUTHORIZATION] = "Bearer " + @auth_token
45
- request.headers[CONTENT_TYPE] = APPLICATION_JSON
46
- request.headers[CLIENT_VERSION] = client_version_header_value
47
- end
48
- rescue Faraday::ClientError
49
- UI.user_error!("#{ErrorMessage::INVALID_TESTERS} \nEmails: #{emails} \nGroup Aliases: #{group_aliases}")
50
- end
51
- UI.success("✅ Added testers/groups.")
52
- end
53
-
54
- # Update release notes for the specified app release. Skips this
55
- # step if no notes are passed in (release_notes is nil/empty).
56
- #
57
- # args
58
- # release_name - App release resource name, returned by upload_status endpoint
59
- # release_notes - String of notes for this release
60
- #
61
- # Returns a hash of the release
62
- #
63
- # Throws a user_error if the release_notes are invalid
64
- def update_release_notes(release_name, release_notes)
65
- payload = {
66
- name: release_name,
67
- releaseNotes: {
68
- text: release_notes
69
- }
70
- }
71
- response = connection.patch(update_release_notes_url(release_name), payload.to_json) do |request|
72
- request.headers[AUTHORIZATION] = "Bearer " + @auth_token
73
- request.headers[CONTENT_TYPE] = APPLICATION_JSON
74
- request.headers[CLIENT_VERSION] = client_version_header_value
75
- end
76
- UI.success("✅ Posted release notes.")
77
- response.body
78
- rescue Faraday::ClientError => e
79
- error = ErrorResponse.new(e.response)
80
- UI.user_error!("#{ErrorMessage::INVALID_RELEASE_NOTES}: #{error.message}")
81
- end
82
-
83
- # Get AAB info (Android apps only)
84
- #
85
- # args
86
- # app_name - Firebase App resource name
87
- #
88
- # Throws a user_error if the app hasn't been onboarded to App Distribution
89
- def get_aab_info(app_name)
90
- begin
91
- response = connection.get(aab_info_url(app_name)) do |request|
92
- request.headers[AUTHORIZATION] = "Bearer " + @auth_token
93
- request.headers[CLIENT_VERSION] = client_version_header_value
94
- end
95
- rescue Faraday::ResourceNotFound
96
- UI.user_error!("#{ErrorMessage::INVALID_APP_ID}: #{app_name}")
97
- end
98
-
99
- AabInfo.new(response.body)
100
- end
101
-
102
- # Uploads the app binary to the Firebase API
103
- #
104
- # args
105
- # app_name - Firebase App resource name
106
- # binary_path - Absolute path to your app's aab/apk/ipa file
107
- # platform - 'android' or 'ios'
108
- # timeout - The amount of seconds before the upload will timeout, if not completed
109
- #
110
- # Throws a user_error if the binary file does not exist
111
- def upload_binary(app_name, binary_path, platform, timeout)
112
- response = connection.post(binary_upload_url(app_name), read_binary(binary_path)) do |request|
113
- request.options.timeout = timeout # seconds
114
- request.headers[AUTHORIZATION] = "Bearer " + @auth_token
115
- request.headers[CONTENT_TYPE] = APPLICATION_OCTET_STREAM
116
- request.headers[CLIENT_VERSION] = client_version_header_value
117
- request.headers["X-Goog-Upload-File-Name"] = File.basename(binary_path)
118
- request.headers["X-Goog-Upload-Protocol"] = "raw"
119
- end
120
-
121
- response.body[:name] || ''
122
- rescue Errno::ENOENT # Raised when binary_path file does not exist
123
- binary_type = binary_type_from_path(binary_path)
124
- UI.user_error!("#{ErrorMessage.binary_not_found(binary_type)}: #{binary_path}")
125
- end
126
-
127
- # Uploads the binary file if it has not already been uploaded
128
- # Takes at least POLLING_INTERVAL_SECONDS between polling get_upload_status
129
- #
130
- # args
131
- # app_name - Firebase App resource name
132
- # binary_path - Absolute path to your app's aab/apk/ipa file
133
- # timeout - The amount of seconds before the upload will timeout, if not completed
134
- #
135
- # Returns a `UploadStatusResponse` with the upload is complete.
136
- #
137
- # Crashes if the number of polling retries exceeds MAX_POLLING_RETRIES or if the binary cannot
138
- # be uploaded.
139
- def upload(app_name, binary_path, platform, timeout)
140
- binary_type = binary_type_from_path(binary_path)
141
-
142
- UI.message("⌛ Uploading the #{binary_type}.")
143
- operation_name = upload_binary(app_name, binary_path, platform, timeout)
144
-
145
- upload_status_response = get_upload_status(operation_name)
146
- MAX_POLLING_RETRIES.times do
147
- if upload_status_response.success?
148
- if upload_status_response.release_updated?
149
- UI.success("✅ Uploaded #{binary_type} successfully; updated provisioning profile of existing release #{upload_status_response.release_version}.")
150
- break
151
- elsif upload_status_response.release_unmodified?
152
- UI.success("✅ The same #{binary_type} was found in release #{upload_status_response.release_version} with no changes, skipping.")
153
- break
154
- else
155
- UI.success("✅ Uploaded #{binary_type} successfully and created release #{upload_status_response.release_version}.")
156
- end
157
- break
158
- elsif upload_status_response.in_progress?
159
- sleep(POLLING_INTERVAL_SECONDS)
160
- upload_status_response = get_upload_status(operation_name)
161
- else
162
- if !upload_status_response.error_message.nil?
163
- UI.user_error!("#{ErrorMessage.upload_binary_error(binary_type)}: #{upload_status_response.error_message}")
164
- else
165
- UI.user_error!(ErrorMessage.upload_binary_error(binary_type))
166
- end
167
- end
168
- end
169
- unless upload_status_response.success?
170
- UI.crash!("It took longer than expected to process your #{binary_type}, please try again.")
171
- end
172
-
173
- upload_status_response
174
- end
175
-
176
- # Fetches the status of an uploaded binary
177
- #
178
- # args
179
- # operation_name - Upload operation name (with binary hash)
180
- #
181
- # Returns the `done` status, as well as a release, error, or nil
182
- def get_upload_status(operation_name)
183
- response = connection.get(upload_status_url(operation_name)) do |request|
184
- request.headers[AUTHORIZATION] = "Bearer " + @auth_token
185
- request.headers[CLIENT_VERSION] = client_version_header_value
186
- end
187
- UploadStatusResponse.new(response.body)
188
- end
189
-
190
19
  # Get tester UDIDs
191
20
  #
192
21
  # args
@@ -205,233 +34,14 @@ module Fastlane
205
34
  response.body[:testerUdids] || []
206
35
  end
207
36
 
208
- # Create testers
209
- #
210
- # args
211
- # project_number - Firebase project number
212
- # emails - An array of emails to be created as testers. A maximum of
213
- # 1000 testers can be created at a time.
214
- #
215
- def add_testers(project_number, emails)
216
- payload = { emails: emails }
217
- connection.post(add_testers_url(project_number), payload.to_json) do |request|
218
- request.headers[AUTHORIZATION] = "Bearer " + @auth_token
219
- request.headers[CONTENT_TYPE] = APPLICATION_JSON
220
- request.headers[CLIENT_VERSION] = client_version_header_value
221
- end
222
- rescue Faraday::BadRequestError
223
- UI.user_error!(ErrorMessage::INVALID_EMAIL_ADDRESS)
224
- rescue Faraday::ResourceNotFound
225
- UI.user_error!(ErrorMessage::INVALID_PROJECT)
226
- rescue Faraday::ClientError => e
227
- if e.response[:status] == 429
228
- UI.user_error!(ErrorMessage::TESTER_LIMIT_VIOLATION)
229
- else
230
- raise e
231
- end
232
- end
233
-
234
- # Delete testers
235
- #
236
- # args
237
- # project_number - Firebase project number
238
- # emails - An array of emails to be deleted as testers. A maximum of
239
- # 1000 testers can be deleted at a time.
240
- #
241
- # Returns the number of testers that were deleted
242
- def remove_testers(project_number, emails)
243
- payload = { emails: emails }
244
- response = connection.post(remove_testers_url(project_number), payload.to_json) do |request|
245
- request.headers[AUTHORIZATION] = "Bearer " + @auth_token
246
- request.headers[CONTENT_TYPE] = APPLICATION_JSON
247
- request.headers[CLIENT_VERSION] = client_version_header_value
248
- end
249
- response.body[:emails] ? response.body[:emails].count : 0
250
- rescue Faraday::ResourceNotFound
251
- UI.user_error!(ErrorMessage::INVALID_PROJECT)
252
- end
253
-
254
- # Create tester group
255
- #
256
- # args
257
- # project_number - Firebase project number
258
- # group_alias - Alias of the tester group
259
- # display_name - Display name of the tester group
260
- #
261
- def create_group(project_number, group_alias, display_name)
262
- payload = { name: "projects/#{project_number}/groups/#{group_alias}",
263
- displayName: display_name }
264
- response = connection.post(add_tester_group_url(project_number), payload.to_json) do |request|
265
- request.params["groupId"] = group_alias
266
- request.headers[AUTHORIZATION] = "Bearer " + @auth_token
267
- request.headers[CONTENT_TYPE] = APPLICATION_JSON
268
- request.headers[CLIENT_VERSION] = client_version_header_value
269
- end
270
- response.body
271
- rescue Faraday::BadRequestError
272
- UI.user_error!(ErrorMessage::INVALID_TESTER_GROUP_NAME)
273
- rescue Faraday::ResourceNotFound
274
- UI.user_error!(ErrorMessage::INVALID_PROJECT)
275
- rescue Faraday::ConflictError
276
- UI.important("Tester group #{group_alias} already exists.")
277
- return {
278
- name: "projects/#{project_number}/groups/#{group_alias}"
279
- }
280
- rescue Faraday::ClientError => e
281
- raise e
282
- end
283
-
284
- # Add testers to group
285
- #
286
- # args
287
- # project_number - Firebase project number
288
- # group_alias - Alias of the tester group
289
- # emails - An array of emails to be added to the group.
290
- # A maximum of 1000 testers can be added at a time, if creating missing testers is enabled.
291
- # create_missing_testers - If true, missing testers will be created and added to the group.
292
- #
293
- def add_testers_to_group(project_number, group_alias, emails, create_missing_testers = false)
294
- payload = { emails: emails,
295
- createMissingTesters: create_missing_testers }
296
- response = connection.post(add_testers_to_group_url(project_number, group_alias), payload.to_json) do |request|
297
- request.headers[AUTHORIZATION] = "Bearer " + @auth_token
298
- request.headers[CONTENT_TYPE] = APPLICATION_JSON
299
- request.headers[CLIENT_VERSION] = client_version_header_value
300
- end
301
- response.body
302
- rescue Faraday::BadRequestError
303
- UI.user_error!(ErrorMessage::INVALID_EMAIL_ADDRESS)
304
- rescue Faraday::ResourceNotFound
305
- UI.user_error!(ErrorMessage::INVALID_TESTER_GROUP)
306
- rescue Faraday::ClientError => e
307
- raise e
308
- end
309
-
310
- # Remove testers from group
311
- #
312
- # args
313
- # project_number - Firebase project number
314
- # group_alias - Alias of the tester group
315
- # emails - An array of emails to be removed from the group.
316
- #
317
- def remove_testers_from_group(project_number, group_alias, emails)
318
- payload = { emails: emails }
319
- response = connection.post(remove_testers_from_group_url(project_number, group_alias), payload.to_json) do |request|
320
- request.headers[AUTHORIZATION] = "Bearer " + @auth_token
321
- request.headers[CONTENT_TYPE] = APPLICATION_JSON
322
- request.headers[CLIENT_VERSION] = client_version_header_value
323
- end
324
- response.body
325
- rescue Faraday::BadRequestError
326
- UI.user_error!(ErrorMessage::INVALID_EMAIL_ADDRESS)
327
- rescue Faraday::ResourceNotFound
328
- UI.user_error!(ErrorMessage::INVALID_TESTER_GROUP)
329
- rescue Faraday::ClientError => e
330
- raise e
331
- end
332
-
333
- # Delete tester group
334
- #
335
- # args
336
- # project_number - Firebase project number
337
- # group_alias - Alias of the tester group
338
- #
339
- def delete_group(project_number, group_alias)
340
- response = connection.delete(delete_tester_group_url(project_number, group_alias)) do |request|
341
- request.headers[AUTHORIZATION] = "Bearer " + @auth_token
342
- request.headers[CONTENT_TYPE] = APPLICATION_JSON
343
- request.headers[CLIENT_VERSION] = client_version_header_value
344
- end
345
- response.body
346
- rescue Faraday::ResourceNotFound
347
- UI.user_error!(ErrorMessage::INVALID_TESTER_GROUP)
348
- end
349
-
350
- # List releases
351
- #
352
- # args
353
- # app_name - Firebase App resource name
354
- # page_size - The number of releases to return in the page
355
- # page_token - A page token, received from a previous call
356
- #
357
- # Returns the response body. Throws a user_error if the app hasn't been onboarded to App Distribution.
358
- def list_releases(app_name, page_size = 100, page_token = nil)
359
- begin
360
- response = connection.get(list_releases_url(app_name), { pageSize: page_size.to_s, pageToken: page_token }) do |request|
361
- request.headers[AUTHORIZATION] = "Bearer " + @auth_token
362
- request.headers[CLIENT_VERSION] = client_version_header_value
363
- end
364
- rescue Faraday::ResourceNotFound
365
- UI.user_error!("#{ErrorMessage::INVALID_APP_ID}: #{app_name}")
366
- end
367
-
368
- response.body
369
- end
370
-
371
37
  private
372
38
 
373
39
  def client_version_header_value
374
40
  "fastlane/#{Fastlane::FirebaseAppDistribution::VERSION}"
375
41
  end
376
42
 
377
- def v1alpha_apps_url(app_id)
378
- "/v1alpha/apps/#{app_id}"
379
- end
380
-
381
- def v1_apps_url(app_name)
382
- "/v1/#{app_name}"
383
- end
384
-
385
- def aab_info_url(app_name)
386
- "#{v1_apps_url(app_name)}/aabInfo"
387
- end
388
-
389
- def update_release_notes_url(release_name)
390
- "/v1/#{release_name}?updateMask=release_notes.text"
391
- end
392
-
393
- def distribute_url(release_name)
394
- "/v1/#{release_name}:distribute"
395
- end
396
-
397
- def binary_upload_url(app_name)
398
- "/upload#{v1_apps_url(app_name)}/releases:upload"
399
- end
400
-
401
- def upload_status_url(operation_name)
402
- "/v1/#{operation_name}"
403
- end
404
-
405
- def list_releases_url(app_name)
406
- "#{v1_apps_url(app_name)}/releases"
407
- end
408
-
409
43
  def get_udids_url(app_id)
410
- "#{v1alpha_apps_url(app_id)}/testers:getTesterUdids"
411
- end
412
-
413
- def add_testers_url(project_number)
414
- "/v1/projects/#{project_number}/testers:batchAdd"
415
- end
416
-
417
- def remove_testers_url(project_number)
418
- "/v1/projects/#{project_number}/testers:batchRemove"
419
- end
420
-
421
- def add_tester_group_url(project_number)
422
- "/v1/projects/#{project_number}/groups"
423
- end
424
-
425
- def delete_tester_group_url(project_number, group_alias)
426
- "/v1/projects/#{project_number}/groups/#{group_alias}"
427
- end
428
-
429
- def add_testers_to_group_url(project_number, group_alias)
430
- "/v1/projects/#{project_number}/groups/#{group_alias}:batchJoin"
431
- end
432
-
433
- def remove_testers_from_group_url(project_number, group_alias)
434
- "/v1/projects/#{project_number}/groups/#{group_alias}:batchLeave"
44
+ "/v1alpha/apps/#{app_id}/testers:getTesterUdids"
435
45
  end
436
46
 
437
47
  def connection
@@ -442,11 +52,6 @@ module Fastlane
442
52
  conn.adapter(Faraday.default_adapter)
443
53
  end
444
54
  end
445
-
446
- def read_binary(path)
447
- # File must be read in binary mode to work on Windows
448
- File.open(path, 'rb').read
449
- end
450
55
  end
451
56
  end
452
57
  end
@@ -1,4 +1,6 @@
1
+ require 'googleauth'
1
2
  require 'fastlane_core/ui/ui'
3
+
2
4
  module Fastlane
3
5
  UI = FastlaneCore::UI unless Fastlane.const_defined?("UI")
4
6
  module Auth
@@ -13,8 +15,8 @@ module Fastlane
13
15
  CLIENT_ID = "563584335869-fgrhgmd47bqnekij5i8b5pr03ho849e6.apps.googleusercontent.com"
14
16
  CLIENT_SECRET = "j9iVZfS8kkCEFUPaAeJV0sAi"
15
17
 
16
- # Returns the auth token for any of the auth methods (Firebase CLI token,
17
- # Google service account, firebase-tools). To ensure that a specific
18
+ # Returns an authorization object for any of the auth methods (Firebase CLI token,
19
+ # Application Default Credentials, firebase-tools). To ensure that a specific
18
20
  # auth method is used, unset all other auth variables/parameters to nil/empty
19
21
  #
20
22
  # args
@@ -23,43 +25,45 @@ module Fastlane
23
25
  # debug - Whether to enable debug-level logging
24
26
  #
25
27
  # env variables
26
- # GOOGLE_APPLICATION_CREDENTIALS - see google_service_path
27
28
  # FIREBASE_TOKEN - see firebase_cli_token
28
29
  #
29
30
  # Crashes if given invalid or missing credentials
30
- def fetch_auth_token(google_service_path, firebase_cli_token, debug = false)
31
+ def get_authorization(google_service_path, firebase_cli_token, debug = false)
31
32
  if !google_service_path.nil? && !google_service_path.empty?
32
33
  UI.message("🔐 Authenticating with --service_credentials_file path parameter: #{google_service_path}")
33
- token = service_account(google_service_path, debug)
34
+ service_account(google_service_path, debug)
34
35
  elsif !firebase_cli_token.nil? && !firebase_cli_token.empty?
35
36
  UI.message("🔐 Authenticating with --firebase_cli_token parameter")
36
- token = firebase_token(firebase_cli_token, debug)
37
+ firebase_token(firebase_cli_token, debug)
37
38
  elsif !ENV["FIREBASE_TOKEN"].nil? && !ENV["FIREBASE_TOKEN"].empty?
38
39
  UI.message("🔐 Authenticating with FIREBASE_TOKEN environment variable")
39
- token = firebase_token(ENV["FIREBASE_TOKEN"], debug)
40
- elsif !ENV["GOOGLE_APPLICATION_CREDENTIALS"].nil? && !ENV["GOOGLE_APPLICATION_CREDENTIALS"].empty?
41
- UI.message("🔐 Authenticating with GOOGLE_APPLICATION_CREDENTIALS environment variable: #{ENV['GOOGLE_APPLICATION_CREDENTIALS']}")
42
- token = service_account(ENV["GOOGLE_APPLICATION_CREDENTIALS"], debug)
40
+ firebase_token(ENV["FIREBASE_TOKEN"], debug)
41
+ elsif !application_default_creds.nil?
42
+ UI.message("🔐 Authenticating with Application Default Credentials")
43
+ application_default_creds
43
44
  elsif (refresh_token = refresh_token_from_firebase_tools)
44
- UI.message("🔐 No authentication method specified. Using cached Firebase CLI credentials.")
45
- token = firebase_token(refresh_token, debug)
45
+ UI.message("🔐 No authentication method found. Using cached Firebase CLI credentials.")
46
+ firebase_token(refresh_token, debug)
46
47
  else
47
48
  UI.user_error!(ErrorMessage::MISSING_CREDENTIALS)
49
+ nil
48
50
  end
49
- token
50
51
  end
51
52
 
52
53
  private
53
54
 
55
+ def application_default_creds
56
+ Google::Auth.get_application_default([SCOPE])
57
+ rescue
58
+ nil
59
+ end
60
+
54
61
  def refresh_token_from_firebase_tools
55
62
  config_path = format_config_path
56
63
  if File.exist?(config_path)
57
64
  begin
58
65
  firebase_tools_tokens = JSON.parse(File.read(config_path))['tokens']
59
- if firebase_tools_tokens.nil?
60
- UI.user_error!(ErrorMessage::EMPTY_TOKENS_FIELD)
61
- return
62
- end
66
+ return if firebase_tools_tokens.nil?
63
67
  refresh_token = firebase_tools_tokens['refresh_token']
64
68
  rescue JSON::ParserError
65
69
  UI.user_error!(ErrorMessage::PARSE_FIREBASE_TOOLS_JSON_ERROR)
@@ -84,7 +88,7 @@ module Fastlane
84
88
  refresh_token: refresh_token
85
89
  )
86
90
  client.fetch_access_token!
87
- client.access_token
91
+ client
88
92
  rescue Signet::AuthorizationError => error
89
93
  error_message = ErrorMessage::REFRESH_TOKEN_ERROR
90
94
  if debug
@@ -101,7 +105,8 @@ module Fastlane
101
105
  json_key_io: File.open(google_service_path),
102
106
  scope: SCOPE
103
107
  )
104
- service_account_credentials.fetch_access_token!["access_token"]
108
+ service_account_credentials.fetch_access_token!
109
+ service_account_credentials
105
110
  rescue Errno::ENOENT
106
111
  UI.user_error!("#{ErrorMessage::SERVICE_CREDENTIALS_NOT_FOUND}: #{google_service_path}")
107
112
  rescue Signet::AuthorizationError => error
@@ -1,5 +1,5 @@
1
1
  module ErrorMessage
2
- MISSING_CREDENTIALS = "Missing authentication credentials. Check that your Firebase refresh token is set or that your service account file path is correct and try again."
2
+ MISSING_CREDENTIALS = "Missing authentication credentials. Set up Application Default Credentials, your Firebase refresh token, or sign in with the Firebase CLI, and try again."
3
3
  MISSING_APP_ID = "Missing app id. Please check that the app parameter is set and try again"
4
4
  SERVICE_CREDENTIALS_NOT_FOUND = "Service credentials file does not exist. Please check the service credentials path and try again"
5
5
  PARSE_SERVICE_CREDENTIALS_ERROR = "Failed to extract service account information from the service credentials file"
@@ -15,7 +15,7 @@ module ErrorMessage
15
15
  INVALID_TESTERS = "Could not enable access for testers. Check that the tester emails are formatted correctly, the groups exist and you are using group aliases (not group names) for specifying groups."
16
16
  INVALID_TESTER_GROUP = "App Distribution could not find your tester group. Make sure that it exists before trying to add testers, and that the group alias is specified correctly."
17
17
  INVALID_TESTER_GROUP_NAME = "The tester group name should be 4-63 characters, and valid characters are /[a-z][0-9]-/."
18
- INVALID_RELEASE_NOTES = "Failed to add release notes"
18
+ INVALID_RELEASE_NOTES = "Failed to set release notes"
19
19
  SERVICE_CREDENTIALS_ERROR = "App Distribution could not generate credentials from the service credentials file specified"
20
20
  PLAY_ACCOUNT_NOT_LINKED = "This project is not linked to a Google Play account."
21
21
  APP_NOT_PUBLISHED = "This app is not published in the Google Play console."
@@ -23,7 +23,6 @@ module ErrorMessage
23
23
  PLAY_IAS_TERMS_NOT_ACCEPTED = "You must accept the Play Internal App Sharing (IAS) terms to upload AABs."
24
24
  INVALID_EMAIL_ADDRESS = "You passed an invalid email address."
25
25
  TESTER_LIMIT_VIOLATION = "Creating testers would exceed tester limit"
26
- EMPTY_TOKENS_FIELD = "Unable to find \"tokens\" field in the firebase-tools.json file. Ensure that the file has a tokens field and try again"
27
26
 
28
27
  def self.aab_upload_error(aab_state)
29
28
  "Failed to process the AAB: #{aab_state}"
@@ -27,7 +27,7 @@ module Fastlane
27
27
  # Returns the array representation of a string with trimmed comma
28
28
  # seperated values.
29
29
  def string_to_array(string)
30
- return nil if string.nil? || string.empty?
30
+ return [] if string.nil?
31
31
  # Strip string and then strip individual values
32
32
  string.strip.split(",").map(&:strip)
33
33
  end
@@ -54,7 +54,36 @@ module Fastlane
54
54
  end
55
55
 
56
56
  def app_name_from_app_id(app_id)
57
- "projects/#{app_id.split(':')[1]}/apps/#{app_id}"
57
+ "#{project_name(app_id.split(':')[1])}/apps/#{app_id}"
58
+ end
59
+
60
+ def project_name(project_number)
61
+ "projects/#{project_number}"
62
+ end
63
+
64
+ def group_name(project_number, group_alias)
65
+ "#{project_name(project_number)}/groups/#{group_alias}"
66
+ end
67
+
68
+ def init_client(service_credentials_file, firebase_cli_token, debug = false)
69
+ if debug
70
+ UI.important("Warning: Debug logging enabled. Output may include sensitive information.")
71
+ Google::Apis.logger.level = Logger::DEBUG
72
+ end
73
+
74
+ Google::Apis::ClientOptions.default.application_name = "fastlane"
75
+ Google::Apis::ClientOptions.default.application_version = Fastlane::FirebaseAppDistribution::VERSION
76
+ client = Google::Apis::FirebaseappdistributionV1::FirebaseAppDistributionService.new
77
+ client.authorization = get_authorization(service_credentials_file, firebase_cli_token)
78
+ client
79
+ end
80
+
81
+ def deep_symbolize_keys(hash)
82
+ result = {}
83
+ hash.each do |key, value|
84
+ result[key.to_sym] = value.kind_of?(Hash) ? deep_symbolize_keys(value) : value
85
+ end
86
+ result
58
87
  end
59
88
  end
60
89
  end
@@ -1,5 +1,5 @@
1
1
  module Fastlane
2
2
  module FirebaseAppDistribution
3
- VERSION = "0.6.1"
3
+ VERSION = "0.7.0.pre.1"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fastlane-plugin-firebase_app_distribution
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.1
4
+ version: 0.7.0.pre.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stefan Natchev
@@ -10,8 +10,36 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2023-06-07 00:00:00.000000000 Z
13
+ date: 2023-07-26 00:00:00.000000000 Z
14
14
  dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: google-api-client
17
+ requirement: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - "~>"
20
+ - !ruby/object:Gem::Version
21
+ version: '0.38'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - "~>"
27
+ - !ruby/object:Gem::Version
28
+ version: '0.38'
29
+ - !ruby/object:Gem::Dependency
30
+ name: google-apis-firebaseappdistribution_v1
31
+ requirement: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - "~>"
34
+ - !ruby/object:Gem::Version
35
+ version: 0.3.0
36
+ type: :runtime
37
+ prerelease: false
38
+ version_requirements: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - "~>"
41
+ - !ruby/object:Gem::Version
42
+ version: 0.3.0
15
43
  - !ruby/object:Gem::Dependency
16
44
  name: pry
17
45
  requirement: !ruby/object:Gem::Requirement
@@ -158,13 +186,10 @@ files:
158
186
  - lib/fastlane/plugin/firebase_app_distribution/actions/firebase_app_distribution_get_latest_release.rb
159
187
  - lib/fastlane/plugin/firebase_app_distribution/actions/firebase_app_distribution_get_udids.rb
160
188
  - lib/fastlane/plugin/firebase_app_distribution/actions/firebase_app_distribution_remove_testers_action.rb
161
- - lib/fastlane/plugin/firebase_app_distribution/client/aab_info.rb
162
- - lib/fastlane/plugin/firebase_app_distribution/client/error_response.rb
163
189
  - lib/fastlane/plugin/firebase_app_distribution/client/firebase_app_distribution_api_client.rb
164
190
  - lib/fastlane/plugin/firebase_app_distribution/helper/firebase_app_distribution_auth_client.rb
165
191
  - lib/fastlane/plugin/firebase_app_distribution/helper/firebase_app_distribution_error_message.rb
166
192
  - lib/fastlane/plugin/firebase_app_distribution/helper/firebase_app_distribution_helper.rb
167
- - lib/fastlane/plugin/firebase_app_distribution/helper/upload_status_response.rb
168
193
  - lib/fastlane/plugin/firebase_app_distribution/version.rb
169
194
  homepage: https://github.com/fastlane/fastlane-plugin-firebase_app_distribution
170
195
  licenses:
@@ -181,9 +206,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
181
206
  version: '0'
182
207
  required_rubygems_version: !ruby/object:Gem::Requirement
183
208
  requirements:
184
- - - ">="
209
+ - - ">"
185
210
  - !ruby/object:Gem::Version
186
- version: '0'
211
+ version: 1.3.1
187
212
  requirements: []
188
213
  rubygems_version: 3.4.10
189
214
  signing_key: