fastlane-plugin-firebase_app_distribution 0.2.0.pre.2 → 0.2.2.pre.1

Sign up to get free protection for your applications and to get access to all the features.
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: []