fastlane-plugin-firebase_app_distribution 0.2.0.pre.2 → 0.2.2.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: 7387fdbb5db28a63ea91ef6e4feb290f4cdb71b93e8c7132595098f94f1ffc16
4
- data.tar.gz: d24c551ec1c81f90ca38307aa75f7c3884982fdc58de2911f54b5971056a4a99
3
+ metadata.gz: 3bb962d7530d1226f6f4811578bebe6086c1e1d82222ed5d935e3314cb933a50
4
+ data.tar.gz: e2cd536750a1b8e328cba78a43329d4bab7988d74fee1f83ececf19963812acd
5
5
  SHA512:
6
- metadata.gz: fe83dbc6eaca609c5471732598f004775ff2139d9d24487bb5021d821a909dfce61f955166c3ed1e115186909c7b455a0578237923845a5015d5ac776c57fe5c
7
- data.tar.gz: 440ac81fb3b05743c511d22f2096c099a636cfc6df06a8d4a8703f9dff8d727c4841f6218e4503cec22d765d2379dc5bbca4ae76bc2b98dcb79007d2b45533ce
6
+ metadata.gz: b439ab0e98082e51dc96f0f29009aa7ffe83aca6c347f3967ee85e68077161cec8621aeac6861470266226132eec2fa1ae2cd3676be081cf97cc909b948e614d
7
+ data.tar.gz: 9b5777d5e274a92963b57253a81a9866a461f2024f4abf9226b247a65f6e0b4a2f03fc7c439133935115921aadec767048a0a8e68cb03d6a652db36152b7ab60
@@ -13,7 +13,6 @@ require_relative '../helper/firebase_app_distribution_auth_client'
13
13
  module Fastlane
14
14
  module Actions
15
15
  class FirebaseAppDistributionAction < Action
16
- DEFAULT_FIREBASE_CLI_PATH = `which firebase`
17
16
  FIREBASECMD_ACTION = "appdistribution:distribute".freeze
18
17
 
19
18
  extend Auth::FirebaseAppDistributionAuthClient
@@ -21,9 +20,6 @@ module Fastlane
21
20
 
22
21
  def self.run(params)
23
22
  params.values # to validate all inputs before looking for the ipa/apk
24
- auth_token = fetch_auth_token(params[:service_credentials_file], params[:firebase_cli_token])
25
- fad_api_client = Client::FirebaseAppDistributionApiClient.new(auth_token, platform)
26
- binary_path = params[:ipa_path] || params[:apk_path]
27
23
 
28
24
  if params[:app] # Set app_id if it is specified as a parameter
29
25
  app_id = params[:app]
@@ -33,10 +29,16 @@ module Fastlane
33
29
  app_id = get_ios_app_id_from_archive(archive_path)
34
30
  end
35
31
  end
36
-
37
32
  if app_id.nil?
38
33
  UI.crash!(ErrorMessage::MISSING_APP_ID)
39
34
  end
35
+
36
+ platform = lane_platform || platform_from_app_id(app_id)
37
+ binary_path = binary_path_from_platform(platform, params[:ipa_path], params[:apk_path])
38
+
39
+ auth_token = fetch_auth_token(params[:service_credentials_file], params[:firebase_cli_token])
40
+ fad_api_client = Client::FirebaseAppDistributionApiClient.new(auth_token, platform)
41
+
40
42
  release_id = fad_api_client.upload(app_id, binary_path, platform.to_s)
41
43
  if release_id.nil?
42
44
  return
@@ -50,7 +52,7 @@ module Fastlane
50
52
  emails = string_to_array(testers)
51
53
  group_ids = string_to_array(groups)
52
54
  fad_api_client.enable_access(app_id, release_id, emails, group_ids)
53
- UI.success("App Distribution upload finished successfully")
55
+ UI.success("🎉 App Distribution upload finished successfully.")
54
56
  end
55
57
 
56
58
  def self.description
@@ -66,16 +68,35 @@ module Fastlane
66
68
  "Release your beta builds with Firebase App Distribution"
67
69
  end
68
70
 
69
- def self.platform
70
- @platform ||= Actions.lane_context[Actions::SharedValues::PLATFORM_NAME]
71
+ def self.lane_platform
72
+ Actions.lane_context[Actions::SharedValues::PLATFORM_NAME]
73
+ end
74
+
75
+ def self.platform_from_app_id(app_id)
76
+ if app_id.include?(':ios:')
77
+ :ios
78
+ elsif app_id.include?(':android:')
79
+ :android
80
+ end
81
+ end
82
+
83
+ def self.binary_path_from_platform(platform, ipa_path, apk_path)
84
+ case platform
85
+ when :ios
86
+ ipa_path
87
+ when :android
88
+ apk_path
89
+ else
90
+ ipa_path || apk_path
91
+ end
71
92
  end
72
93
 
73
94
  def self.available_options
74
- if platform == :ios || platform.nil?
95
+ if lane_platform == :ios || lane_platform.nil?
75
96
  ipa_path_default = Dir["*.ipa"].sort_by { |x| File.mtime(x) }.last
76
97
  end
77
98
 
78
- if platform == :android
99
+ if lane_platform == :android
79
100
  apk_path_default = Dir["*.apk"].last || Dir[File.join("app", "build", "outputs", "apk", "app-release.apk")].last
80
101
  end
81
102
 
@@ -106,22 +127,10 @@ module Fastlane
106
127
  optional: true,
107
128
  type: String),
108
129
  FastlaneCore::ConfigItem.new(key: :firebase_cli_path,
130
+ deprecated: "This plugin no longer uses the Firebase CLI",
109
131
  env_name: "FIREBASEAPPDISTRO_FIREBASE_CLI_PATH",
110
132
  description: "The absolute path of the firebase cli command",
111
- default_value: DEFAULT_FIREBASE_CLI_PATH,
112
- default_value_dynamic: true,
113
- optional: false,
114
- type: String,
115
- verify_block: proc do |value|
116
- value.chomp!
117
- if value.to_s == "" || !File.exist?(value)
118
- UI.user_error!("firebase_cli_path: missing path to firebase cli tool. Please install firebase in $PATH or specify path")
119
- end
120
-
121
- unless is_firebasecmd_supported?(value)
122
- UI.user_error!("firebase_cli_path: `#{value}` does not support the `#{FIREBASECMD_ACTION}` command. Please download (https://appdistro.page.link/firebase-cli-download) or specify the path to the correct version of firebse")
123
- end
124
- end),
133
+ type: String),
125
134
  FastlaneCore::ConfigItem.new(key: :groups,
126
135
  env_name: "FIREBASEAPPDISTRO_GROUPS",
127
136
  description: "The groups used for distribution, separated by commas",
@@ -188,18 +197,6 @@ module Fastlane
188
197
  CODE
189
198
  ]
190
199
  end
191
-
192
- ## TODO: figure out if we can surpress color output.
193
- def self.is_firebasecmd_supported?(cmd)
194
- outerr, status = Open3.capture2e(cmd, "--non-interactive", FIREBASECMD_ACTION, "--help")
195
- return false unless status.success?
196
-
197
- if outerr =~ /is not a Firebase command/
198
- return false
199
- end
200
-
201
- true
202
- end
203
200
  end
204
201
  end
205
202
  end
@@ -16,20 +16,20 @@ module Fastlane
16
16
  authorizer = Google::Auth::UserAuthorizer.new(client_id, SCOPE, nil)
17
17
  url = authorizer.get_authorization_url(base_url: OOB_URI)
18
18
 
19
- UI.message("Please open the following address in your browser:")
19
+ UI.message("Open the following address in your browser and sign in with your Google account:")
20
20
  UI.message(url)
21
21
  UI.message("")
22
22
  code = UI.input("Enter the resulting code here: ")
23
23
  credentials = authorizer.get_credentials_from_code(code: code, base_url: OOB_URI)
24
-
25
- UI.message("Refresh Token: #{credentials.refresh_token}")
26
24
  UI.message("")
27
- UI.message("Set the refresh token as a FIREBASE_TOKEN environment variable")
25
+
26
+ UI.success("Set the refresh token as the FIREBASE_TOKEN environment variable")
27
+ UI.success("Refresh Token: #{credentials.refresh_token}")
28
28
  rescue Signet::AuthorizationError
29
- UI.error("The code you entered was invalid. Ensure that you have copied the code correctly.")
29
+ UI.error("The code you entered is invalid. Copy and paste the code and try again.")
30
30
  rescue => error
31
31
  UI.error(error.to_s)
32
- UI.crash!("An error has occured please login again.")
32
+ UI.crash!("An error has occured, please login again.")
33
33
  end
34
34
 
35
35
  #####################################################
@@ -11,7 +11,10 @@ module Fastlane
11
11
 
12
12
  def initialize(auth_token, platform)
13
13
  @auth_token = auth_token
14
- if platform == :ios || platform.nil?
14
+
15
+ if platform.nil?
16
+ @binary_type = "IPA/APK"
17
+ elsif platform == :ios
15
18
  @binary_type = "IPA"
16
19
  else
17
20
  @binary_type = "APK"
@@ -30,7 +33,7 @@ module Fastlane
30
33
  # Throws a user_error if app_id, emails, or group_ids are invalid
31
34
  def enable_access(app_id, release_id, emails, group_ids)
32
35
  if (emails.nil? || emails.empty?) && (group_ids.nil? || group_ids.empty?)
33
- UI.message("No testers passed in. Skipping this step")
36
+ UI.success("No testers passed in. Skipping this step.")
34
37
  return
35
38
  end
36
39
  payload = { emails: emails, groupIds: group_ids }
@@ -43,7 +46,7 @@ module Fastlane
43
46
  rescue Faraday::ClientError
44
47
  UI.user_error!("#{ErrorMessage::INVALID_TESTERS} \nEmails: #{emails} \nGroups: #{group_ids}")
45
48
  end
46
- UI.success("Added testers/groups successfully.")
49
+ UI.success("Added testers/groups.")
47
50
  end
48
51
 
49
52
  # Posts notes for the specified app release. Skips this
@@ -58,7 +61,7 @@ module Fastlane
58
61
  def post_notes(app_id, release_id, release_notes)
59
62
  payload = { releaseNotes: { releaseNotes: release_notes } }
60
63
  if release_notes.nil? || release_notes.empty?
61
- UI.message("No release notes passed in. Skipping this step.")
64
+ UI.success("No release notes passed in. Skipping this step.")
62
65
  return
63
66
  end
64
67
  begin
@@ -70,41 +73,57 @@ module Fastlane
70
73
  # rescue Faraday::ClientError
71
74
  # UI.user_error!("#{ErrorMessage::INVALID_RELEASE_ID}: #{release_id}")
72
75
  end
73
- UI.success("Release notes have been posted.")
76
+ UI.success(" Posted release notes.")
74
77
  end
75
78
 
79
+ # Returns the url encoded upload token used for get_upload_status calls:
80
+ # projects/<project-number>/apps/<app-id>/releases/-/binaries/<binary-hash>
81
+ #
82
+ # args
83
+ # app_id - Firebase App ID
84
+ # binary_path - Absolute path to your app's apk/ipa file
85
+ #
86
+ # Throws a user_error if an invalid app id is passed in, the binary file does
87
+ # not exist, or invalid auth credentials are used (e.g. wrong project permissions)
76
88
  def get_upload_token(app_id, binary_path)
77
- begin
78
- binary_hash = Digest::SHA256.hexdigest(File.open(binary_path).read)
79
- rescue Errno::ENOENT
89
+ if binary_path.nil? || !File.exist?(binary_path)
80
90
  UI.crash!("#{ErrorMessage.binary_not_found(@binary_type)}: #{binary_path}")
81
91
  end
92
+ binary_hash = Digest::SHA256.hexdigest(read_binary(binary_path))
82
93
 
83
94
  begin
84
95
  response = connection.get(v1_apps_url(app_id)) do |request|
85
96
  request.headers["Authorization"] = "Bearer " + @auth_token
86
97
  end
87
98
  rescue Faraday::ResourceNotFound
88
- UI.crash!("#{ErrorMessage::INVALID_APP_ID}: #{app_id}")
99
+ UI.user_error!("#{ErrorMessage::INVALID_APP_ID}: #{app_id}")
89
100
  end
90
101
  contact_email = response.body[:contactEmail]
91
102
  if contact_email.nil? || contact_email.strip.empty?
92
- UI.crash!(ErrorMessage::GET_APP_NO_CONTACT_EMAIL_ERROR)
103
+ UI.user_error!(ErrorMessage::GET_APP_NO_CONTACT_EMAIL_ERROR)
93
104
  end
94
105
  return upload_token_format(response.body[:appId], response.body[:projectNumber], binary_hash)
95
106
  end
96
107
 
108
+ # Uploads the app binary to the Firebase API
109
+ #
110
+ # args
111
+ # app_id - Firebase App ID
112
+ # binary_path - Absolute path to your app's apk/ipa file
113
+ # platform - 'android' or 'ios'
114
+ #
115
+ # Throws a user_error if an invalid app id is passed in, or if the binary file does not exist
97
116
  def upload_binary(app_id, binary_path, platform)
98
- connection.post(binary_upload_url(app_id), File.open(binary_path).read) do |request|
117
+ connection.post(binary_upload_url(app_id), read_binary(binary_path)) do |request|
99
118
  request.headers["Authorization"] = "Bearer " + @auth_token
100
119
  request.headers["X-APP-DISTRO-API-CLIENT-ID"] = "fastlane"
101
120
  request.headers["X-APP-DISTRO-API-CLIENT-TYPE"] = platform
102
121
  request.headers["X-APP-DISTRO-API-CLIENT-VERSION"] = Fastlane::FirebaseAppDistribution::VERSION
103
122
  end
104
123
  rescue Faraday::ResourceNotFound
105
- UI.crash!("#{ErrorMessage::INVALID_APP_ID}: #{app_id}")
106
- rescue Errno::ENOENT
107
- UI.crash!("#{ErrorMessage.binary_not_found(@binary_type)}: #{binary_path}")
124
+ UI.user_error!("#{ErrorMessage::INVALID_APP_ID}: #{app_id}")
125
+ rescue Errno::ENOENT # Raised when binary_path file does not exist
126
+ UI.user_error!("#{ErrorMessage.binary_not_found(@binary_type)}: #{binary_path}")
108
127
  end
109
128
 
110
129
  # Uploads the binary file if it has not already been uploaded
@@ -122,17 +141,16 @@ module Fastlane
122
141
  upload_token = get_upload_token(app_id, binary_path)
123
142
  upload_status_response = get_upload_status(app_id, upload_token)
124
143
  if upload_status_response.success? || upload_status_response.already_uploaded?
125
- UI.success("This #{@binary_type} has been uploaded before. Skipping upload step.")
144
+ UI.success("This #{@binary_type} has been uploaded before. Skipping upload step.")
126
145
  else
127
- UI.message("This #{@binary_type} has not been uploaded before")
128
- UI.message("Uploading the #{@binary_type}.")
129
146
  unless upload_status_response.in_progress?
147
+ UI.message("⌛ Uploading the #{@binary_type}.")
130
148
  upload_binary(app_id, binary_path, platform)
131
149
  end
132
150
  MAX_POLLING_RETRIES.times do
133
151
  upload_status_response = get_upload_status(app_id, upload_token)
134
152
  if upload_status_response.success? || upload_status_response.already_uploaded?
135
- UI.success("Uploaded #{@binary_type} Successfully!")
153
+ UI.success("Uploaded the #{@binary_type}.")
136
154
  break
137
155
  elsif upload_status_response.in_progress?
138
156
  sleep(POLLING_INTERVAL_SECONDS)
@@ -152,14 +170,22 @@ module Fastlane
152
170
  upload_status_response.release_id
153
171
  end
154
172
 
155
- # Gets the upload status for the app release.
156
- def get_upload_status(app_id, app_token)
173
+ # Fetches the status of an uploaded binary
174
+ #
175
+ # args
176
+ # app_id - Firebase App ID
177
+ # upload_token - URL encoded upload token
178
+ #
179
+ # Returns the release ID on a successful release, otherwise returns nil.
180
+ #
181
+ # Throws a user_error if an invalid app_id is passed in
182
+ def get_upload_status(app_id, upload_token)
157
183
  begin
158
- response = connection.get(upload_status_url(app_id, app_token)) do |request|
184
+ response = connection.get(upload_status_url(app_id, upload_token)) do |request|
159
185
  request.headers["Authorization"] = "Bearer " + @auth_token
160
186
  end
161
187
  rescue Faraday::ResourceNotFound
162
- UI.crash!("#{ErrorMessage::INVALID_APP_ID}: #{app_id}")
188
+ UI.user_error!("#{ErrorMessage::INVALID_APP_ID}: #{app_id}")
163
189
  end
164
190
  return UploadStatusResponse.new(response.body)
165
191
  end
@@ -197,6 +223,11 @@ module Fastlane
197
223
  conn.adapter(Faraday.default_adapter)
198
224
  end
199
225
  end
226
+
227
+ def read_binary(path)
228
+ # File must be read in binary mode to work on Windows
229
+ File.open(path, 'rb').read
230
+ end
200
231
  end
201
232
  end
202
233
  end
@@ -38,7 +38,7 @@ module Fastlane
38
38
  else
39
39
  UI.user_error!(ErrorMessage::MISSING_CREDENTIALS)
40
40
  end
41
- UI.success("Successfully authenticated!")
41
+ UI.success("🔐 Authenticated successfully.")
42
42
  token
43
43
  end
44
44
 
@@ -1,20 +1,20 @@
1
1
  module ErrorMessage
2
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."
3
- MISSING_APP_ID = "Missing app id. Please check that it was passed in and try again"
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"
6
6
  UPLOAD_RELEASE_NOTES_ERROR = "App Distribution halted because it had a problem uploading release notes"
7
7
  UPLOAD_TESTERS_ERROR = "App Distribution halted because it had a problem adding testers/groups"
8
8
  GET_RELEASE_TIMEOUT = "App Distribution failed to fetch release information"
9
- REFRESH_TOKEN_ERROR = "Could not generate credentials from the refresh token specified."
9
+ REFRESH_TOKEN_ERROR = "App Distribution could not generate credentials from the refresh token specified."
10
10
  GET_APP_ERROR = "App Distribution failed to fetch app information"
11
11
  APP_NOT_ONBOARDED_ERROR = "App Distribution not onboarded"
12
12
  GET_APP_NO_CONTACT_EMAIL_ERROR = "App Distribution could not find a contact email associated with this app. Contact Email"
13
13
  INVALID_APP_ID = "App Distribution could not find your app. Make sure to onboard your app by pressing the \"Get started\" button on the App Distribution page in the Firebase console: https://console.firebase.google.com/project/_/appdistribution. App ID"
14
14
  INVALID_PATH = "Could not read content from"
15
- INVALID_TESTERS = "Could not enable access for testers. Ensure that the groups exist and the tester emails are formatted correctly"
15
+ INVALID_TESTERS = "Could not enable access for testers. Check that the groups exist and the tester emails are formatted correctly"
16
16
  INVALID_RELEASE_ID = "App distribution failed to fetch release with id"
17
- SERVICE_CREDENTIALS_ERROR = "Could not generate credentials from the service credentials file specified. Service Account Path"
17
+ SERVICE_CREDENTIALS_ERROR = "App Distribution could not generate credentials from the service credentials file specified. Service Account Path"
18
18
 
19
19
  def self.binary_not_found(binary_type)
20
20
  "Could not find the #{binary_type}. Make sure you set the #{binary_type} path parameter to point to your #{binary_type}"
@@ -1,5 +1,5 @@
1
1
  module Fastlane
2
2
  module FirebaseAppDistribution
3
- VERSION = "0.2.0.pre.2"
3
+ VERSION = "0.2.2.pre.1"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,16 +1,16 @@
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.0.pre.2
4
+ version: 0.2.2.pre.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stefan Natchev
8
8
  - Manny Jimenez
9
9
  - Alonso Salas Infante
10
- autorequire:
10
+ autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2020-08-06 00:00:00.000000000 Z
13
+ date: 2020-09-17 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: pry
@@ -138,7 +138,7 @@ dependencies:
138
138
  - - ">="
139
139
  - !ruby/object:Gem::Version
140
140
  version: 2.127.1
141
- description:
141
+ description:
142
142
  email:
143
143
  - snatchev@google.com
144
144
  - mannyjimenez@google.com
@@ -162,7 +162,7 @@ homepage: https://github.com/fastlane/fastlane-plugin-firebase_app_distribution
162
162
  licenses:
163
163
  - MIT
164
164
  metadata: {}
165
- post_install_message:
165
+ post_install_message:
166
166
  rdoc_options: []
167
167
  require_paths:
168
168
  - lib
@@ -177,8 +177,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
177
177
  - !ruby/object:Gem::Version
178
178
  version: 1.3.1
179
179
  requirements: []
180
- rubygems_version: 3.1.4
181
- signing_key:
180
+ rubygems_version: 3.1.2
181
+ signing_key:
182
182
  specification_version: 4
183
183
  summary: Release your beta builds to Firebase App Distribution. https://firebase.google.com/docs/app-distribution
184
184
  test_files: []