fastlane-plugin-firebase_app_distribution 0.2.5 → 0.2.6.pre.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1415793a828ae696b67f1568c6393a9ae68eb6dbf17fc2a379904e3256201c1b
4
- data.tar.gz: b1e08e8e78359f62c2c76c868c8e80e90bdf3d463951072ecf77aaa46a232ad1
3
+ metadata.gz: d129a8d78fc5bca84c4e7484dbe02436ee9cd4ef9e9005bec4e1646401b9b143
4
+ data.tar.gz: 1677a9d201117796c171ed8a0a9472b69bc8b763bdd5492e3a3fd8f3dae19d84
5
5
  SHA512:
6
- metadata.gz: a3c2f313a6401ac052c48329d9f21228c084983c6f6a3c252e22c494c4216b57ee68882668e1f3f6f0e5f639b3389b0701d97dad3c3542289099450aea2f1952
7
- data.tar.gz: 29c7622c069712c0012429c26e3ad7e306499c6a29d7a7d837185a008837831dba795787a16930817dbbdbb3aabb0f38f37c06094208d2e1376cff030c79733d
6
+ metadata.gz: 1c6e3502a696a1d759f838028812a526745e6d11fe678e26a829ead65fd8114b4244565695d338b1d60ef34cb1129b70948e87c8d297c72334abc46e9bbc20ec
7
+ data.tar.gz: 47504b8df8a313b588aea6c5fa8b7d8cebc5d7ea66117c0025b73f53e6f529bbc443e395c66baa357248c81b864ed81f5cfe46cd957c42c92d03e63e16cbc89a
@@ -13,26 +13,46 @@ require_relative '../helper/firebase_app_distribution_auth_client'
13
13
  module Fastlane
14
14
  module Actions
15
15
  class FirebaseAppDistributionAction < Action
16
- FIREBASECMD_ACTION = "appdistribution:distribute".freeze
17
-
18
16
  extend Auth::FirebaseAppDistributionAuthClient
19
17
  extend Helper::FirebaseAppDistributionHelper
20
18
 
21
19
  def self.run(params)
22
- params.values # to validate all inputs before looking for the ipa/apk
20
+ params.values # to validate all inputs before looking for the ipa/apk/aab
23
21
 
24
22
  app_id = app_id_from_params(params)
25
23
  platform = lane_platform || platform_from_app_id(app_id)
26
- binary_path = binary_path_from_platform(platform, params[:ipa_path], params[:apk_path])
24
+
25
+ binary_path = get_binary_path(platform, params)
26
+ UI.user_error!("Couldn't find binary") if binary_path.nil?
27
+ UI.user_error!("Couldn't find binary at path #{binary_path}") unless File.exist?(binary_path)
28
+ binary_type = binary_type_from_path(binary_path)
27
29
 
28
30
  auth_token = fetch_auth_token(params[:service_credentials_file], params[:firebase_cli_token])
29
- fad_api_client = Client::FirebaseAppDistributionApiClient.new(auth_token, platform, params[:debug])
31
+ fad_api_client = Client::FirebaseAppDistributionApiClient.new(auth_token, params[:debug])
30
32
 
31
- release_id = fad_api_client.upload(app_id, binary_path, platform.to_s)
33
+ # If binary is an AAB get FULL view of app which includes the aab_state
34
+ app_view = binary_type == :AAB ? 'FULL' : 'BASIC'
35
+ app = fad_api_client.get_app(app_id, app_view)
36
+ validate_app!(app, binary_type)
37
+
38
+ release_id = fad_api_client.upload(app.project_number, app_id, binary_path, platform.to_s)
32
39
  if release_id.nil?
33
40
  return
34
41
  end
35
42
 
43
+ if binary_type == :AAB && app.aab_certificate.empty?
44
+ updated_app = fad_api_client.get_app(app_id)
45
+ unless updated_app.aab_certificate.empty?
46
+ UI.message("After you upload an AAB for the first time, App Distribution " \
47
+ "generates a new test certificate. All AAB uploads are re-signed with this test " \
48
+ "certificate. Use the certificate fingerprints below to register your app " \
49
+ "signing key with API providers, such as Google Sign-In and Google Maps.\n" \
50
+ "MD-1 certificate fingerprint: #{updated_app.aab_certificate.md5_certificate_hash}\n" \
51
+ "SHA-1 certificate fingerprint: #{updated_app.aab_certificate.sha1_certificate_hash}\n" \
52
+ "SHA-256 certificate fingerprint: #{updated_app.aab_certificate.sha256_certificate_hash}")
53
+ end
54
+ end
55
+
36
56
  release_notes = get_value_from_value_or_file(params[:release_notes], params[:release_notes_file])
37
57
  fad_api_client.post_notes(app_id, release_id, release_notes)
38
58
 
@@ -90,37 +110,56 @@ module Fastlane
90
110
  end
91
111
  end
92
112
 
93
- def self.binary_path_from_platform(platform, ipa_path, apk_path)
94
- case platform
95
- when :ios
96
- ipa_path
97
- when :android
98
- apk_path
99
- else
100
- ipa_path || apk_path
113
+ def self.get_binary_path(platform, params)
114
+ if platform == :ios
115
+ return params[:ipa_path] ||
116
+ Actions.lane_context[SharedValues::IPA_OUTPUT_PATH] ||
117
+ Dir["*.ipa"].sort_by { |x| File.mtime(x) }.last
118
+ end
119
+
120
+ if platform == :android
121
+ return params[:apk_path] || params[:android_artifact_path] if params[:apk_path] || params[:android_artifact_path]
122
+
123
+ if params[:android_artifact_type] == 'AAB'
124
+ return Actions.lane_context[SharedValues::GRADLE_AAB_OUTPUT_PATH] ||
125
+ Dir["*.aab"].last ||
126
+ Dir[File.join("app", "build", "outputs", "bundle", "release", "app-release.aab")].last
127
+ end
128
+
129
+ return Actions.lane_context[SharedValues::GRADLE_APK_OUTPUT_PATH] ||
130
+ Dir["*.apk"].last ||
131
+ Dir[File.join("app", "build", "outputs", "apk", "release", "app-release.apk")].last
101
132
  end
102
133
  end
103
134
 
104
- def self.available_options
105
- if lane_platform == :ios || lane_platform.nil?
106
- ipa_path_default = Dir["*.ipa"].sort_by { |x| File.mtime(x) }.last
135
+ def self.validate_app!(app, binary_type)
136
+ if app.contact_email.nil? || app.contact_email.strip.empty?
137
+ UI.user_error!(ErrorMessage::GET_APP_NO_CONTACT_EMAIL_ERROR)
107
138
  end
108
139
 
109
- if lane_platform == :android
110
- apk_path_default = Dir["*.apk"].last || Dir[File.join("app", "build", "outputs", "apk", "app-release.apk")].last
140
+ if binary_type == :AAB && app.aab_state != App::AabState::ACTIVE && app.aab_state != App::AabState::UNAVAILABLE
141
+ case app.aab_state
142
+ when App::AabState::PLAY_ACCOUNT_NOT_LINKED
143
+ UI.user_error!(ErrorMessage::PLAY_ACCOUNT_NOT_LINKED)
144
+ when App::AabState::APP_NOT_PUBLISHED
145
+ UI.user_error!(ErrorMessage::APP_NOT_PUBLISHED)
146
+ when App::AabState::NO_APP_WITH_GIVEN_BUNDLE_ID_IN_PLAY_ACCOUNT
147
+ UI.user_error!(ErrorMessage::NO_APP_WITH_GIVEN_BUNDLE_ID_IN_PLAY_ACCOUNT)
148
+ when App::AabState::PLAY_IAS_TERMS_NOT_ACCEPTED
149
+ UI.user_error!(ErrorMessage::PLAY_IAS_TERMS_NOT_ACCEPTED)
150
+ else
151
+ UI.user_error!(ErrorMessage.aab_upload_error(app.aab_state))
152
+ end
111
153
  end
154
+ end
112
155
 
156
+ def self.available_options
113
157
  [
114
158
  # iOS Specific
115
159
  FastlaneCore::ConfigItem.new(key: :ipa_path,
116
160
  env_name: "FIREBASEAPPDISTRO_IPA_PATH",
117
161
  description: "Path to your IPA file. Optional if you use the _gym_ or _xcodebuild_ action",
118
- default_value: Actions.lane_context[SharedValues::IPA_OUTPUT_PATH] || ipa_path_default,
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),
162
+ optional: true),
124
163
  FastlaneCore::ConfigItem.new(key: :googleservice_info_plist_path,
125
164
  env_name: "GOOGLESERVICE_INFO_PLIST_PATH",
126
165
  description: "Path to your GoogleService-Info.plist file, relative to the archived product path",
@@ -130,12 +169,21 @@ module Fastlane
130
169
  # Android Specific
131
170
  FastlaneCore::ConfigItem.new(key: :apk_path,
132
171
  env_name: "FIREBASEAPPDISTRO_APK_PATH",
172
+ deprecated: "The apk_path parameter is deprecated. Please use android_artifact_path instead",
133
173
  description: "Path to your APK file",
134
- default_value: Actions.lane_context[SharedValues::GRADLE_APK_OUTPUT_PATH] || apk_path_default,
174
+ optional: true),
175
+ FastlaneCore::ConfigItem.new(key: :android_artifact_path,
176
+ env_name: "FIREBASEAPPDISTRO_ANDROID_ARTIFACT_PATH",
177
+ description: "Path to your APK or AAB file",
178
+ optional: true),
179
+ FastlaneCore::ConfigItem.new(key: :android_artifact_type,
180
+ env_name: "FIREBASEAPPDISTRO_ANDROID_ARTIFACT_TYPE",
181
+ description: "Android artifact type. Set to 'APK' or 'AAB'. Defaults to 'APK' if not set",
182
+ default_value: "APK",
135
183
  default_value_dynamic: true,
136
184
  optional: true,
137
185
  verify_block: proc do |value|
138
- UI.user_error!("firebase_app_distribution: Couldn't find apk file at path '#{value}'") unless File.exist?(value)
186
+ UI.user_error!("firebase_app_distribution: '#{value}' is not a valid value for android_artifact_path. Should be 'APK' or 'AAB'") unless ['APK', 'AAB'].include?(value)
139
187
  end),
140
188
  FastlaneCore::ConfigItem.new(key: :app,
141
189
  env_name: "FIREBASEAPPDISTRO_APP",
@@ -8,6 +8,9 @@ module Fastlane
8
8
  class FirebaseAppDistributionLoginAction < Action
9
9
  OOB_URI = "urn:ietf:wg:oauth:2.0:oob"
10
10
  SCOPE = "https://www.googleapis.com/auth/cloud-platform"
11
+
12
+ # In this type of application, the client secret is not treated as a secret.
13
+ # See: https://developers.google.com/identity/protocols/OAuth2InstalledApp
11
14
  CLIENT_ID = "563584335869-fgrhgmd47bqnekij5i8b5pr03ho849e6.apps.googleusercontent.com"
12
15
  CLIENT_SECRET = "j9iVZfS8kkCEFUPaAeJV0sAi"
13
16
 
@@ -0,0 +1,23 @@
1
+ class AabCertificate
2
+ def initialize(response)
3
+ @response = response || {}
4
+ end
5
+
6
+ def md5_certificate_hash
7
+ @response[:certificateHashMd5]
8
+ end
9
+
10
+ def sha1_certificate_hash
11
+ @response[:certificateHashSha1]
12
+ end
13
+
14
+ def sha256_certificate_hash
15
+ @response[:certificateHashSha256]
16
+ end
17
+
18
+ def empty?
19
+ (md5_certificate_hash.nil? || md5_certificate_hash.empty?) &&
20
+ (sha1_certificate_hash.nil? || sha1_certificate_hash.empty?) &&
21
+ (sha256_certificate_hash.nil? || sha256_certificate_hash.empty?)
22
+ end
23
+ end
@@ -0,0 +1,37 @@
1
+ require_relative 'aab_certificate'
2
+
3
+ class App
4
+ # AAB states
5
+ class AabState
6
+ UNSPECIFIED = "AAB_STATE_UNSPECIFIED"
7
+ PLAY_ACCOUNT_NOT_LINKED = "PLAY_ACCOUNT_NOT_LINKED"
8
+ NO_APP_WITH_GIVEN_BUNDLE_ID_IN_PLAY_ACCOUNT = "NO_APP_WITH_GIVEN_BUNDLE_ID_IN_PLAY_ACCOUNT"
9
+ APP_NOT_PUBLISHED = "APP_NOT_PUBLISHED"
10
+ PLAY_IAS_TERMS_NOT_ACCEPTED = "PLAY_IAS_TERMS_NOT_ACCEPTED"
11
+ ACTIVE = "ACTIVE"
12
+ UNAVAILABLE = "AAB_STATE_UNAVAILABLE"
13
+ end
14
+
15
+ attr_reader :aab_certificate
16
+
17
+ def initialize(response)
18
+ @response = response
19
+ @aab_certificate = AabCertificate.new(response[:aabCertificate])
20
+ end
21
+
22
+ def app_id
23
+ @response[:appId]
24
+ end
25
+
26
+ def project_number
27
+ @response[:projectNumber]
28
+ end
29
+
30
+ def contact_email
31
+ @response[:contactEmail]
32
+ end
33
+
34
+ def aab_state
35
+ @response[:aabState]
36
+ end
37
+ end
@@ -1,10 +1,14 @@
1
1
  require 'fastlane_core/ui/ui'
2
2
  require_relative '../actions/firebase_app_distribution_login'
3
3
  require_relative '../client/error_response'
4
+ require_relative '../client/app'
5
+ require_relative '../helper/firebase_app_distribution_helper'
4
6
 
5
7
  module Fastlane
6
8
  module Client
7
9
  class FirebaseAppDistributionApiClient
10
+ include Helper::FirebaseAppDistributionHelper
11
+
8
12
  BASE_URL = "https://firebaseappdistribution.googleapis.com"
9
13
  TOKEN_CREDENTIAL_URI = "https://oauth2.googleapis.com/token"
10
14
  MAX_POLLING_RETRIES = 60
@@ -15,17 +19,9 @@ module Fastlane
15
19
  APPLICATION_JSON = "application/json"
16
20
  APPLICATION_OCTET_STREAM = "application/octet-stream"
17
21
 
18
- def initialize(auth_token, platform, debug = false)
22
+ def initialize(auth_token, debug = false)
19
23
  @auth_token = auth_token
20
24
  @debug = debug
21
-
22
- if platform.nil?
23
- @binary_type = "IPA/APK"
24
- elsif platform == :ios
25
- @binary_type = "IPA"
26
- else
27
- @binary_type = "APK"
28
- end
29
25
  end
30
26
 
31
27
  # Enables tester access to the specified app release. Skips this
@@ -82,40 +78,29 @@ module Fastlane
82
78
  UI.success("✅ Posted release notes.")
83
79
  end
84
80
 
85
- # Returns the url encoded upload token used for get_upload_status calls:
86
- # projects/<project-number>/apps/<app-id>/releases/-/binaries/<binary-hash>
81
+ # Get app
87
82
  #
88
83
  # args
89
84
  # app_id - Firebase App ID
90
- # binary_path - Absolute path to your app's apk/ipa file
91
85
  #
92
- # Throws a user_error if an invalid app id is passed in, the binary file does
93
- # not exist, or invalid auth credentials are used (e.g. wrong project permissions)
94
- def get_upload_token(app_id, binary_path)
95
- if binary_path.nil? || !File.exist?(binary_path)
96
- UI.crash!("#{ErrorMessage.binary_not_found(@binary_type)}: #{binary_path}")
97
- end
98
- binary_hash = Digest::SHA256.hexdigest(read_binary(binary_path))
99
-
86
+ # Throws a user_error if the app hasn't been onboarded to App Distribution
87
+ def get_app(app_id, app_view = 'BASIC')
100
88
  begin
101
- response = connection.get(v1_apps_url(app_id)) do |request|
89
+ response = connection.get("#{v1_apps_url(app_id)}?appView=#{app_view}") do |request|
102
90
  request.headers[AUTHORIZATION] = "Bearer " + @auth_token
103
91
  end
104
92
  rescue Faraday::ResourceNotFound
105
93
  UI.user_error!("#{ErrorMessage::INVALID_APP_ID}: #{app_id}")
106
94
  end
107
- contact_email = response.body[:contactEmail]
108
- if contact_email.nil? || contact_email.strip.empty?
109
- UI.user_error!(ErrorMessage::GET_APP_NO_CONTACT_EMAIL_ERROR)
110
- end
111
- return upload_token_format(response.body[:appId], response.body[:projectNumber], binary_hash)
95
+
96
+ App.new(response.body)
112
97
  end
113
98
 
114
99
  # Uploads the app binary to the Firebase API
115
100
  #
116
101
  # args
117
102
  # app_id - Firebase App ID
118
- # binary_path - Absolute path to your app's apk/ipa file
103
+ # binary_path - Absolute path to your app's aab/apk/ipa file
119
104
  # platform - 'android' or 'ios'
120
105
  #
121
106
  # Throws a user_error if the binary file does not exist
@@ -126,49 +111,55 @@ module Fastlane
126
111
  request.headers["X-APP-DISTRO-API-CLIENT-ID"] = "fastlane"
127
112
  request.headers["X-APP-DISTRO-API-CLIENT-TYPE"] = platform
128
113
  request.headers["X-APP-DISTRO-API-CLIENT-VERSION"] = Fastlane::FirebaseAppDistribution::VERSION
114
+ request.headers["X-GOOG-UPLOAD-FILE-NAME"] = File.basename(binary_path)
115
+ request.headers["X-GOOG-UPLOAD-PROTOCOL"] = "raw"
129
116
  end
130
117
  rescue Errno::ENOENT # Raised when binary_path file does not exist
131
- UI.user_error!("#{ErrorMessage.binary_not_found(@binary_type)}: #{binary_path}")
118
+ binary_type = binary_type_from_path(binary_path)
119
+ UI.user_error!("#{ErrorMessage.binary_not_found(binary_type)}: #{binary_path}")
132
120
  end
133
121
 
134
122
  # Uploads the binary file if it has not already been uploaded
135
123
  # Takes at least POLLING_INTERVAL_SECONDS between polling get_upload_status
136
124
  #
137
125
  # args
138
- # app_id - Firebase App ID
139
- # binary_path - Absolute path to your app's apk/ipa file
126
+ # project_number - Firebase project number
127
+ # app_id - Firebase app ID
128
+ # binary_path - Absolute path to your app's aab/apk/ipa file
140
129
  #
141
130
  # Returns the release_id on a successful release, otherwise returns nil.
142
131
  #
143
132
  # Throws a UI error if the number of polling retries exceeds MAX_POLLING_RETRIES
144
133
  # Crashes if not able to upload the binary
145
- def upload(app_id, binary_path, platform)
146
- upload_token = get_upload_token(app_id, binary_path)
134
+ def upload(project_number, app_id, binary_path, platform)
135
+ binary_type = binary_type_from_path(binary_path)
136
+
137
+ upload_token = get_upload_token(project_number, app_id, binary_path)
147
138
  upload_status_response = get_upload_status(app_id, upload_token)
148
139
  if upload_status_response.success? || upload_status_response.already_uploaded?
149
- UI.success("✅ This #{@binary_type} has been uploaded before. Skipping upload step.")
140
+ UI.success("✅ This #{binary_type} has been uploaded before. Skipping upload step.")
150
141
  else
151
142
  unless upload_status_response.in_progress?
152
- UI.message("⌛ Uploading the #{@binary_type}.")
143
+ UI.message("⌛ Uploading the #{binary_type}.")
153
144
  upload_binary(app_id, binary_path, platform)
154
145
  end
155
146
  MAX_POLLING_RETRIES.times do
156
147
  upload_status_response = get_upload_status(app_id, upload_token)
157
148
  if upload_status_response.success? || upload_status_response.already_uploaded?
158
- UI.success("✅ Uploaded the #{@binary_type}.")
149
+ UI.success("✅ Uploaded the #{binary_type}.")
159
150
  break
160
151
  elsif upload_status_response.in_progress?
161
152
  sleep(POLLING_INTERVAL_SECONDS)
162
153
  else
163
154
  if !upload_status_response.message.nil?
164
- UI.user_error!("#{ErrorMessage.upload_binary_error(@binary_type)}: #{upload_status_response.message}")
155
+ UI.user_error!("#{ErrorMessage.upload_binary_error(binary_type)}: #{upload_status_response.message}")
165
156
  else
166
- UI.user_error!(ErrorMessage.upload_binary_error(@binary_type))
157
+ UI.user_error!(ErrorMessage.upload_binary_error(binary_type))
167
158
  end
168
159
  end
169
160
  end
170
161
  unless upload_status_response.success?
171
- UI.error("It took longer than expected to process your #{@binary_type}, please try again.")
162
+ UI.error("It took longer than expected to process your #{binary_type}, please try again.")
172
163
  return nil
173
164
  end
174
165
  end
@@ -211,7 +202,8 @@ module Fastlane
211
202
  "#{v1_apps_url(app_id)}/upload_status/#{app_token}"
212
203
  end
213
204
 
214
- def upload_token_format(app_id, project_number, binary_hash)
205
+ def get_upload_token(project_number, app_id, binary_path)
206
+ binary_hash = Digest::SHA256.hexdigest(read_binary(binary_path))
215
207
  CGI.escape("projects/#{project_number}/apps/#{app_id}/releases/-/binaries/#{binary_hash}")
216
208
  end
217
209
 
@@ -16,6 +16,14 @@ module ErrorMessage
16
16
  INVALID_RELEASE_ID = "App distribution failed to fetch release with id"
17
17
  INVALID_RELEASE_NOTES = "Failed to add release notes"
18
18
  SERVICE_CREDENTIALS_ERROR = "App Distribution could not generate credentials from the service credentials file specified. Service Account Path"
19
+ PLAY_ACCOUNT_NOT_LINKED = "This project is not linked to a Google Play account."
20
+ APP_NOT_PUBLISHED = "This app is not published in the Google Play console."
21
+ NO_APP_WITH_GIVEN_BUNDLE_ID_IN_PLAY_ACCOUNT = "App with matching package name does not exist in Google Play."
22
+ PLAY_IAS_TERMS_NOT_ACCEPTED = "You must accept the Play Internal App Sharing (IAS) terms to upload AABs."
23
+
24
+ def self.aab_upload_error(aab_state)
25
+ "Failed to process the AAB: #{aab_state}"
26
+ end
19
27
 
20
28
  def self.binary_not_found(binary_type)
21
29
  "Could not find the #{binary_type}. Make sure you set the #{binary_type} path parameter to point to your #{binary_type}"
@@ -4,6 +4,15 @@ module Fastlane
4
4
  UI = FastlaneCore::UI unless Fastlane.const_defined?("UI")
5
5
  module Helper
6
6
  module FirebaseAppDistributionHelper
7
+ def binary_type_from_path(binary_path)
8
+ extension = File.extname(binary_path)
9
+ return :APK if extension == '.apk'
10
+ return :AAB if extension == '.aab'
11
+ return :IPA if extension == '.ipa'
12
+
13
+ UI.user_error!("Unsupported distribution file format, should be .ipa, .apk or .aab")
14
+ end
15
+
7
16
  def get_value_from_value_or_file(value, path)
8
17
  if (value.nil? || value.empty?) && !path.nil?
9
18
  begin
@@ -1,5 +1,5 @@
1
1
  module Fastlane
2
2
  module FirebaseAppDistribution
3
- VERSION = "0.2.5"
3
+ VERSION = "0.2.6.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.2.5
4
+ version: 0.2.6.pre.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stefan Natchev
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2021-01-06 00:00:00.000000000 Z
13
+ date: 2021-03-08 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: pry
@@ -152,6 +152,8 @@ files:
152
152
  - lib/fastlane/plugin/firebase_app_distribution.rb
153
153
  - lib/fastlane/plugin/firebase_app_distribution/actions/firebase_app_distribution_action.rb
154
154
  - lib/fastlane/plugin/firebase_app_distribution/actions/firebase_app_distribution_login.rb
155
+ - lib/fastlane/plugin/firebase_app_distribution/client/aab_certificate.rb
156
+ - lib/fastlane/plugin/firebase_app_distribution/client/app.rb
155
157
  - lib/fastlane/plugin/firebase_app_distribution/client/error_response.rb
156
158
  - lib/fastlane/plugin/firebase_app_distribution/client/firebase_app_distribution_api_client.rb
157
159
  - lib/fastlane/plugin/firebase_app_distribution/helper/firebase_app_distribution_auth_client.rb
@@ -174,9 +176,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
174
176
  version: '0'
175
177
  required_rubygems_version: !ruby/object:Gem::Requirement
176
178
  requirements:
177
- - - ">="
179
+ - - ">"
178
180
  - !ruby/object:Gem::Version
179
- version: '0'
181
+ version: 1.3.1
180
182
  requirements: []
181
183
  rubygems_version: 3.1.4
182
184
  signing_key: