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 +4 -4
- data/lib/fastlane/plugin/firebase_app_distribution/actions/firebase_app_distribution_action.rb +33 -36
- data/lib/fastlane/plugin/firebase_app_distribution/actions/firebase_app_distribution_login.rb +6 -6
- data/lib/fastlane/plugin/firebase_app_distribution/client/firebase_app_distribution_api_client.rb +53 -22
- data/lib/fastlane/plugin/firebase_app_distribution/helper/firebase_app_distribution_auth_client.rb +1 -1
- data/lib/fastlane/plugin/firebase_app_distribution/helper/firebase_app_distribution_error_message.rb +4 -4
- data/lib/fastlane/plugin/firebase_app_distribution/version.rb +1 -1
- metadata +7 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3bb962d7530d1226f6f4811578bebe6086c1e1d82222ed5d935e3314cb933a50
|
4
|
+
data.tar.gz: e2cd536750a1b8e328cba78a43329d4bab7988d74fee1f83ececf19963812acd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b439ab0e98082e51dc96f0f29009aa7ffe83aca6c347f3967ee85e68077161cec8621aeac6861470266226132eec2fa1ae2cd3676be081cf97cc909b948e614d
|
7
|
+
data.tar.gz: 9b5777d5e274a92963b57253a81a9866a461f2024f4abf9226b247a65f6e0b4a2f03fc7c439133935115921aadec767048a0a8e68cb03d6a652db36152b7ab60
|
data/lib/fastlane/plugin/firebase_app_distribution/actions/firebase_app_distribution_action.rb
CHANGED
@@ -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.
|
70
|
-
|
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
|
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
|
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
|
-
|
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
|
data/lib/fastlane/plugin/firebase_app_distribution/actions/firebase_app_distribution_login.rb
CHANGED
@@ -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("
|
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
|
-
|
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
|
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
|
#####################################################
|
data/lib/fastlane/plugin/firebase_app_distribution/client/firebase_app_distribution_api_client.rb
CHANGED
@@ -11,7 +11,10 @@ module Fastlane
|
|
11
11
|
|
12
12
|
def initialize(auth_token, platform)
|
13
13
|
@auth_token = auth_token
|
14
|
-
|
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.
|
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
|
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.
|
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("
|
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
|
-
|
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.
|
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.
|
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),
|
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.
|
106
|
-
rescue Errno::ENOENT
|
107
|
-
UI.
|
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}
|
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
|
-
#
|
156
|
-
|
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,
|
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.
|
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
|
data/lib/fastlane/plugin/firebase_app_distribution/helper/firebase_app_distribution_error_message.rb
CHANGED
@@ -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
|
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 = "
|
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.
|
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 = "
|
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}"
|
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.
|
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-
|
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.
|
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: []
|