fastlane-plugin-firebase_app_distribution 0.1.4 → 0.2.0.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
- SHA256:
3
- metadata.gz: 727032daa6617cc4ff637760345d66514b0a3f798653cc8b5f05c043e74df730
4
- data.tar.gz: 2981fccbd5bcc75775cc8ffd34e017dddc724346466c8e5dfeeed53c577609aa
2
+ SHA1:
3
+ metadata.gz: ab7379d2d8feb6112f778c3b4a64e2f2181a099a
4
+ data.tar.gz: bdb617b84fb387a5486faee45d23be3043a9d9af
5
5
  SHA512:
6
- metadata.gz: 3f94539379bfca995ed56795ba992905b5f7259c70becaf410e7695bd0a2a6de9ed75a3c4cf158be14fa153678868d026b928772c389feba05e715412b6689a1
7
- data.tar.gz: fd084df5275b9cf21684d3ad14030de4c8c85954457fcb18ca272577dcf07e66875854b1daf2c712042e3ebde363c8240cc648b14b16dfc08d85cf2530851463
6
+ metadata.gz: 69f808e806793eb81839ac45241445c8764884f35c92c25066c86121c5ecb7ebf981371ed347fceadbfb0161df03ac6613fbd3f2aebe42a935783ca55d239df5
7
+ data.tar.gz: 83c298cdfd08b945957f10f9194142423418b89ee5dc17a2718b1506013e79fbba2f94ad11e1b7c0b92a874c3e69731eba327e66f393bb61b99fae0bf423d5b5
@@ -1,8 +1,12 @@
1
- require 'tempfile'
2
1
  require 'fastlane/action'
3
2
  require 'open3'
4
3
  require 'shellwords'
4
+ require 'googleauth'
5
+ require_relative '../helper/upload_status_response'
5
6
  require_relative '../helper/firebase_app_distribution_helper'
7
+ require_relative '../helper/firebase_app_distribution_error_message'
8
+ require_relative '../client/firebase_app_distribution_api_client'
9
+ require_relative '../helper/firebase_app_distribution_auth_client'
6
10
 
7
11
  ## TODO: should always use a file underneath? I think so.
8
12
  ## How should we document the usage of release notes?
@@ -12,28 +16,42 @@ module Fastlane
12
16
  DEFAULT_FIREBASE_CLI_PATH = `which firebase`
13
17
  FIREBASECMD_ACTION = "appdistribution:distribute".freeze
14
18
 
19
+ extend Auth::FirebaseAppDistributionAuthClient
15
20
  extend Helper::FirebaseAppDistributionHelper
16
21
 
17
22
  def self.run(params)
18
23
  params.values # to validate all inputs before looking for the ipa/apk
19
- cmd = [Shellwords.escape(params[:firebase_cli_path].chomp), FIREBASECMD_ACTION]
20
- cmd << Shellwords.escape(params[:ipa_path] || params[:apk_path])
21
- cmd << "--app #{params[:app]}"
22
-
23
- cmd << groups_flag(params)
24
- cmd << testers_flag(params)
25
- cmd << release_notes_flag(params)
26
- cmd << flag_value_if_supplied('--token', :firebase_cli_token, params)
27
- cmd << flag_if_supplied('--debug', :debug, params)
28
-
29
- Actions.sh_control_output(
30
- cmd.compact.join(" "),
31
- print_command: false,
32
- print_command_output: true
33
- )
34
- # make sure we do this, even in the case of an error.
35
- ensure
36
- cleanup_tempfiles
24
+ auth_token = fetch_auth_token(params[:service_credentials_file])
25
+ fad_api_client = Client::FirebaseAppDistributionApiClient.new(auth_token)
26
+ platform = Actions.lane_context[Actions::SharedValues::PLATFORM_NAME]
27
+ binary_path = params[:ipa_path] || params[:apk_path]
28
+
29
+ if params[:app] # Set app_id if it is specified as a parameter
30
+ app_id = params[:app]
31
+ elsif platform == :ios
32
+ archive_path = Actions.lane_context[SharedValues::XCODEBUILD_ARCHIVE]
33
+ if archive_path
34
+ app_id = get_ios_app_id_from_archive(archive_path)
35
+ end
36
+ end
37
+
38
+ if app_id.nil?
39
+ UI.crash!(ErrorMessage::MISSING_APP_ID)
40
+ end
41
+ release_id = fad_api_client.upload(app_id, binary_path)
42
+ if release_id.nil?
43
+ return
44
+ end
45
+
46
+ release_notes = get_value_from_value_or_file(params[:release_notes], params[:release_notes_file])
47
+ fad_api_client.post_notes(app_id, release_id, release_notes)
48
+
49
+ testers = get_value_from_value_or_file(params[:testers], params[:testers_file])
50
+ groups = get_value_from_value_or_file(params[:groups], params[:groups_file])
51
+ emails = string_to_array(testers)
52
+ group_ids = string_to_array(groups)
53
+ fad_api_client.enable_access(app_id, release_id, emails, group_ids)
54
+ UI.success("App Distribution upload finished successfully")
37
55
  end
38
56
 
39
57
  def self.description
@@ -41,7 +59,7 @@ module Fastlane
41
59
  end
42
60
 
43
61
  def self.authors
44
- ["Stefan Natchev"]
62
+ ["Stefan Natchev", "Manny Jimenez Github: mannyjimenez0810, Alonso Salas Infante Github: alonsosalasinfante"]
45
63
  end
46
64
 
47
65
  # supports markdown.
@@ -84,7 +102,7 @@ module Fastlane
84
102
  FastlaneCore::ConfigItem.new(key: :app,
85
103
  env_name: "FIREBASEAPPDISTRO_APP",
86
104
  description: "Your app's Firebase App ID. You can find the App ID in the Firebase console, on the General Settings page",
87
- optional: false,
105
+ optional: true,
88
106
  type: String),
89
107
  FastlaneCore::ConfigItem.new(key: :firebase_cli_path,
90
108
  env_name: "FIREBASEAPPDISTRO_FIREBASE_CLI_PATH",
@@ -143,7 +161,11 @@ module Fastlane
143
161
  description: "Print verbose debug output",
144
162
  optional: true,
145
163
  default_value: false,
146
- is_string: false)
164
+ is_string: false),
165
+ FastlaneCore::ConfigItem.new(key: :service_credentials_file,
166
+ description: "Path to Google service account json",
167
+ optional: true,
168
+ type: String)
147
169
  ]
148
170
  end
149
171
 
@@ -0,0 +1,58 @@
1
+ require 'googleauth'
2
+ require 'googleauth/stores/file_token_store'
3
+ require "google/apis/people_v1"
4
+ require "fileutils"
5
+
6
+ module Fastlane
7
+ module Actions
8
+ class FirebaseAppDistributionLoginAction < Action
9
+ OOB_URI = "urn:ietf:wg:oauth:2.0:oob"
10
+ SCOPE = "https://www.googleapis.com/auth/cloud-platform"
11
+ CLIENT_ID = "563584335869-fgrhgmd47bqnekij5i8b5pr03ho849e6.apps.googleusercontent.com"
12
+ CLIENT_SECRET = "j9iVZfS8kkCEFUPaAeJV0sAi"
13
+
14
+ def self.run(params)
15
+ client_id = Google::Auth::ClientId.new(CLIENT_ID, CLIENT_SECRET)
16
+ authorizer = Google::Auth::UserAuthorizer.new(client_id, SCOPE, nil)
17
+ url = authorizer.get_authorization_url(base_url: OOB_URI)
18
+
19
+ UI.message("Please open the following address in your browser:")
20
+ UI.message(url)
21
+ UI.message("")
22
+ code = UI.input("Enter the resulting code here: ")
23
+ credentials = authorizer.get_credentials_from_code(code: code, base_url: OOB_URI)
24
+
25
+ UI.message("Refresh Token: #{credentials.refresh_token}")
26
+ UI.message("")
27
+ UI.message("Set the refresh token as a FIREBASE_TOKEN environment variable")
28
+ rescue Signet::AuthorizationError
29
+ UI.error("The code you entered was invalid. Ensure that you have copied the code correctly.")
30
+ rescue => error
31
+ UI.error(error.to_s)
32
+ UI.crash!("An error has occured please login again.")
33
+ end
34
+
35
+ #####################################################
36
+ # @!group Documentation
37
+ #####################################################
38
+
39
+ def self.description
40
+ "Authenticate with Firebase App Distribution using a Google account."
41
+ end
42
+
43
+ def self.details
44
+ "Log in to Firebase App Distribution using a Google account to generate an authentication "\
45
+ "token. This token is stored within an environment variable and used to authenticate with your Firebase project. "\
46
+ "See https://firebase.google.com/docs/app-distribution/ios/distribute-fastlane for more information."
47
+ end
48
+
49
+ def self.authors
50
+ ["Manny Jimenez Github: mannyjimenez0810, Alonso Salas Infante Github: alonsosalasinfante"]
51
+ end
52
+
53
+ def self.is_supported?(platform)
54
+ [:ios, :android].include?(platform)
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,185 @@
1
+ require 'fastlane_core/ui/ui'
2
+ require_relative '../actions/firebase_app_distribution_login'
3
+
4
+ module Fastlane
5
+ module Client
6
+ class FirebaseAppDistributionApiClient
7
+ BASE_URL = "https://firebaseappdistribution.googleapis.com"
8
+ TOKEN_CREDENTIAL_URI = "https://oauth2.googleapis.com/token"
9
+ MAX_POLLING_RETRIES = 60
10
+ POLLING_INTERVAL_SECONDS = 2
11
+
12
+ def initialize(auth_token)
13
+ @auth_token = auth_token
14
+ end
15
+
16
+ # Enables tester access to the specified app release. Skips this
17
+ # step if no testers are passed in (emails and group_ids are nil/empty).
18
+ #
19
+ # args
20
+ # app_id - Firebase App ID
21
+ # release_id - App release ID, returned by upload_status endpoint
22
+ # emails - String array of app testers' email addresses
23
+ # group_ids - String array of Firebase tester group IDs
24
+ #
25
+ # Throws a user_error if app_id, emails, or group_ids are invalid
26
+ def enable_access(app_id, release_id, emails, group_ids)
27
+ if (emails.nil? || emails.empty?) && (group_ids.nil? || group_ids.empty?)
28
+ UI.message("No testers passed in. Skipping this step")
29
+ return
30
+ end
31
+ payload = { emails: emails, groupIds: group_ids }
32
+ begin
33
+ connection.post(enable_access_url(app_id, release_id), payload.to_json) do |request|
34
+ request.headers["Authorization"] = "Bearer " + @auth_token
35
+ end
36
+ rescue Faraday::ResourceNotFound
37
+ UI.user_error!("#{ErrorMessage::INVALID_APP_ID}: #{app_id}")
38
+ rescue Faraday::ClientError
39
+ UI.user_error!("#{ErrorMessage::INVALID_TESTERS} \nEmails: #{emails} \nGroups: #{group_ids}")
40
+ end
41
+ end
42
+
43
+ # Posts notes for the specified app release. Skips this
44
+ # step if no notes are passed in (release_notes is nil/empty).
45
+ #
46
+ # args
47
+ # app_id - Firebase App ID
48
+ # release_id - App release ID, returned by upload_status endpoint
49
+ # release_notes - String of notes for this release
50
+ #
51
+ # Throws a user_error if app_id or release_id are invalid
52
+ def post_notes(app_id, release_id, release_notes)
53
+ payload = { releaseNotes: { releaseNotes: release_notes } }
54
+ if release_notes.nil? || release_notes.empty?
55
+ UI.message("No release notes passed in. Skipping this step.")
56
+ return
57
+ end
58
+ begin
59
+ connection.post(release_notes_create_url(app_id, release_id), payload.to_json) do |request|
60
+ request.headers["Authorization"] = "Bearer " + @auth_token
61
+ end
62
+ rescue Faraday::ResourceNotFound
63
+ UI.user_error!("#{ErrorMessage::INVALID_APP_ID}: #{app_id}")
64
+ # rescue Faraday::ClientError
65
+ # UI.user_error!("#{ErrorMessage::INVALID_RELEASE_ID}: #{release_id}")
66
+ end
67
+ UI.success("Release notes have been posted.")
68
+ end
69
+
70
+ def get_upload_token(app_id, binary_path)
71
+ begin
72
+ binary_hash = Digest::SHA256.hexdigest(File.open(binary_path).read)
73
+ rescue Errno::ENOENT
74
+ UI.crash!("#{ErrorMessage::APK_NOT_FOUND}: #{binary_path}")
75
+ end
76
+
77
+ begin
78
+ response = connection.get(v1_apps_url(app_id)) do |request|
79
+ request.headers["Authorization"] = "Bearer " + @auth_token
80
+ end
81
+ rescue Faraday::ResourceNotFound
82
+ UI.crash!("#{ErrorMessage::INVALID_APP_ID}: #{app_id}")
83
+ end
84
+ contact_email = response.body[:contactEmail]
85
+ if contact_email.nil? || contact_email.strip.empty?
86
+ UI.crash!(ErrorMessage::GET_APP_NO_CONTACT_EMAIL_ERROR)
87
+ end
88
+ return upload_token_format(response.body[:appId], response.body[:projectNumber], binary_hash)
89
+ end
90
+
91
+ def upload_binary(app_id, binary_path)
92
+ connection.post(binary_upload_url(app_id), File.open(binary_path).read) do |request|
93
+ request.headers["Authorization"] = "Bearer " + @auth_token
94
+ end
95
+ rescue Faraday::ResourceNotFound
96
+ UI.crash!("#{ErrorMessage::INVALID_APP_ID}: #{app_id}")
97
+ rescue Errno::ENOENT
98
+ UI.crash!("#{ErrorMessage::APK_NOT_FOUND}: #{binary_path}")
99
+ end
100
+
101
+ # Uploads the binary file if it has not already been uploaded
102
+ # Takes at least POLLING_INTERVAL_SECONDS between polling get_upload_status
103
+ #
104
+ # args
105
+ # app_id - Firebase App ID
106
+ # binary_path - Absolute path to your app's apk/ipa file
107
+ #
108
+ # Returns the release_id on a successful release, otherwise returns nil.
109
+ #
110
+ # Throws an error if the number of polling retries exceeds MAX_POLLING_RETRIES
111
+ def upload(app_id, binary_path)
112
+ upload_token = get_upload_token(app_id, binary_path)
113
+ upload_status_response = get_upload_status(app_id, upload_token)
114
+ if upload_status_response.success?
115
+ UI.success("This APK/IPA has been uploaded before. Skipping upload step.")
116
+ else
117
+ UI.message("This APK has not been uploaded before.")
118
+ MAX_POLLING_RETRIES.times do
119
+ if upload_status_response.success?
120
+ UI.success("Uploaded APK/IPA Successfully!")
121
+ break
122
+ elsif upload_status_response.in_progress?
123
+ sleep(POLLING_INTERVAL_SECONDS)
124
+ else
125
+ UI.message("Uploading the APK/IPA.")
126
+ upload_binary(app_id, binary_path)
127
+ end
128
+ upload_status_response = get_upload_status(app_id, upload_token)
129
+ end
130
+ unless upload_status_response.success?
131
+ UI.error("It took longer than expected to process your APK/IPA, please try again.")
132
+ return nil
133
+ end
134
+ end
135
+ upload_status_response.release_id
136
+ end
137
+
138
+ # Gets the upload status for the app release.
139
+ def get_upload_status(app_id, app_token)
140
+ begin
141
+ response = connection.get(upload_status_url(app_id, app_token)) do |request|
142
+ request.headers["Authorization"] = "Bearer " + @auth_token
143
+ end
144
+ rescue Faraday::ResourceNotFound
145
+ UI.crash!("#{ErrorMessage::INVALID_APP_ID}: #{app_id}")
146
+ end
147
+ return UploadStatusResponse.new(response.body)
148
+ end
149
+
150
+ private
151
+
152
+ def v1_apps_url(app_id)
153
+ "/v1alpha/apps/#{app_id}"
154
+ end
155
+
156
+ def release_notes_create_url(app_id, release_id)
157
+ "#{v1_apps_url(app_id)}/releases/#{release_id}/notes"
158
+ end
159
+
160
+ def enable_access_url(app_id, release_id)
161
+ "#{v1_apps_url(app_id)}/releases/#{release_id}/enable_access"
162
+ end
163
+
164
+ def binary_upload_url(app_id)
165
+ "/app-binary-uploads?app_id=#{app_id}"
166
+ end
167
+
168
+ def upload_status_url(app_id, app_token)
169
+ "#{v1_apps_url(app_id)}/upload_status/#{app_token}"
170
+ end
171
+
172
+ def upload_token_format(app_id, project_number, binary_hash)
173
+ CGI.escape("projects/#{project_number}/apps/#{app_id}/releases/-/binaries/#{binary_hash}")
174
+ end
175
+
176
+ def connection
177
+ @connection ||= Faraday.new(url: BASE_URL) do |conn|
178
+ conn.response(:json, parser_options: { symbolize_names: true })
179
+ conn.response(:raise_error) # raise_error middleware will run before the json middleware
180
+ conn.adapter(Faraday.default_adapter)
181
+ end
182
+ end
183
+ end
184
+ end
185
+ end
@@ -0,0 +1,48 @@
1
+ require 'fastlane_core/ui/ui'
2
+ module Fastlane
3
+ UI = FastlaneCore::UI unless Fastlane.const_defined?("UI")
4
+ module Auth
5
+ module FirebaseAppDistributionAuthClient
6
+ TOKEN_CREDENTIAL_URI = "https://oauth2.googleapis.com/token"
7
+
8
+ def fetch_auth_token(google_service_path)
9
+ if !google_service_path.nil? && !google_service_path.empty?
10
+ service_account(google_service_path)
11
+ elsif ENV["FIREBASE_TOKEN"]
12
+ firebase_token
13
+ elsif ENV["GOOGLE_APPLICATION_CREDENTIALS"]
14
+ service_account(ENV["GOOGLE_APPLICATION_CREDENTIALS"])
15
+ else
16
+ UI.crash!(ErrorMessage::MISSING_CREDENTIALS)
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def firebase_token
23
+ begin
24
+ client = Signet::OAuth2::Client.new(
25
+ token_credential_uri: TOKEN_CREDENTIAL_URI,
26
+ client_id: Fastlane::Actions::FirebaseAppDistributionLoginAction::CLIENT_ID,
27
+ client_secret: Fastlane::Actions::FirebaseAppDistributionLoginAction::CLIENT_SECRET,
28
+ refresh_token: ENV["FIREBASE_TOKEN"]
29
+ )
30
+ rescue Signet::AuthorizationError
31
+ UI.crash!(ErrorMessage::REFRESH_TOKEN_ERROR)
32
+ end
33
+ client.fetch_access_token!
34
+ client.access_token
35
+ end
36
+
37
+ def service_account(google_service_path)
38
+ service_account_credentials = Google::Auth::ServiceAccountCredentials.make_creds(
39
+ json_key_io: File.open(google_service_path),
40
+ scope: Fastlane::Actions::FirebaseAppDistributionLoginAction::SCOPE
41
+ )
42
+ service_account_credentials.fetch_access_token!["access_token"]
43
+ rescue Errno::ENOENT
44
+ UI.crash!("#{ErrorMessage::SERVICE_CREDENTIALS_NOT_FOUND}: #{google_service_path}")
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,21 @@
1
+ module ErrorMessage
2
+ MISSING_CREDENTIALS = "Missing credentials. Please check that a refresh token was set or service credentials were passed in and try again"
3
+ APK_NOT_FOUND = "Could not find the APK/IPA. Make sure you set the apk_path parameter to point to your APK/IPA"
4
+ MISSING_APP_ID = "Missing app id. Please check that it was passed in and try again"
5
+ SERVICE_CREDENTIALS_NOT_FOUND = "Service credentials file does not exist. Please check the service credentials path and try again"
6
+ PARSE_SERVICE_CREDENTIALS_ERROR = "Failed to extract service account information from the service credentials file"
7
+ PARSE_APK_METADATA_ERROR = "Failed to extract APK/IPA metadata from the APK/IPA path"
8
+ UPLOAD_RELEASE_NOTES_ERROR = "App Distribution halted because it had a problem uploading release notes"
9
+ UPLOAD_TESTERS_ERROR = "App Distribution halted because it had a problem adding testers/groups"
10
+ UPLOAD_APK_ERROR = "App Distribution halted because it had a problem uploading the APK/IPA"
11
+ APK_PROCESSING_ERROR = "App Distribution failed to process the APK/IPA"
12
+ GET_RELEASE_TIMEOUT = "App Distribution failed to fetch release information"
13
+ REFRESH_TOKEN_ERROR = "Could not generate credentials from the refresh token specified"
14
+ GET_APP_ERROR = "App Distribution failed to fetch app information"
15
+ APP_NOT_ONBOARDED_ERROR = "App Distribution not onboarded"
16
+ GET_APP_NO_CONTACT_EMAIL_ERROR = "App Distribution could not find a contact email associated with this app. Contact Email"
17
+ 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"
18
+ INVALID_PATH = "Could not read content from"
19
+ INVALID_TESTERS = "Could not enable access for testers. Ensure that the groups exist and the tester emails are formatted correctly"
20
+ INVALID_RELEASE_ID = "App distribution failed to fetch release with id"
21
+ end
@@ -1,60 +1,34 @@
1
1
  require 'fastlane_core/ui/ui'
2
-
3
2
  module Fastlane
4
3
  UI = FastlaneCore::UI unless Fastlane.const_defined?("UI")
5
-
6
4
  module Helper
7
5
  module FirebaseAppDistributionHelper
8
- def testers_flag(params)
9
- file_flag_if_supplied("--testers-file", "testers", params)
10
- end
11
-
12
- def groups_flag(params)
13
- file_flag_if_supplied("--groups-file", "groups", params)
14
- end
15
-
16
- def release_notes_flag(params)
17
- file_flag_if_supplied("--release-notes-file", "release_notes", params)
18
- end
19
-
20
- def file_flag_if_supplied(flag, param_name, params)
21
- file = params["#{param_name}_file".to_sym]
22
- file ||= file_for_contents(param_name.to_sym, params)
23
-
24
- if file
25
- return "#{flag} #{file}"
6
+ def get_value_from_value_or_file(value, path)
7
+ if (value.nil? || value.empty?) && !path.nil?
8
+ begin
9
+ return File.open(path).read
10
+ rescue Errno::ENOENT
11
+ UI.crash!("#{ErrorMessage::INVALID_PATH}: #{path}")
12
+ end
26
13
  end
14
+ value
27
15
  end
28
16
 
29
- def flag_value_if_supplied(flag, param_name, params)
30
- "#{flag} #{params[param_name]}" if params[param_name]
31
- end
32
-
33
- def flag_if_supplied(flag, param_name, params)
34
- flag if params[param_name]
35
- end
36
-
37
- ##
38
- # always return a file for a given content
39
- def file_for_contents(parameter_name, params)
40
- if @tempfiles.nil?
41
- @tempfiles = []
42
- end
43
-
44
- contents = params[parameter_name]
45
- return nil if contents.nil?
46
-
47
- file = Tempfile.new(parameter_name.to_s)
48
- file.write(contents)
49
- file.close
50
- @tempfiles << file
51
-
52
- file.path
17
+ # Returns the array representation of a string with comma seperated values.
18
+ #
19
+ # Does not work with strings whose individual values have spaces. EX "Hello World" the space will be removed to "HelloWorld"
20
+ def string_to_array(string)
21
+ return nil if string.nil? || string.empty?
22
+ string_array = string.gsub(/\s+/, '').split(",")
23
+ return string_array
53
24
  end
54
25
 
55
- def cleanup_tempfiles
56
- return if @tempfiles.nil?
57
- @tempfiles.each(&:unlink)
26
+ def get_ios_app_id_from_archive(path)
27
+ app_path = parse_plist("#{path}/Info.plist")["ApplicationProperties"]["ApplicationPath"]
28
+ UI.shell_error!("can't extract application path from Info.plist at #{path}") if app_path.empty?
29
+ identifier = parse_plist("#{path}/Products/#{app_path}/GoogleService-Info.plist")["GOOGLE_APP_ID"]
30
+ UI.shell_error!("can't extract GOOGLE_APP_ID") if identifier.empty?
31
+ return identifier
58
32
  end
59
33
  end
60
34
  end
@@ -0,0 +1,25 @@
1
+ class UploadStatusResponse
2
+ def initialize(response_json_hash)
3
+ @response_json_hash = response_json_hash
4
+ end
5
+
6
+ def status
7
+ @response_json_hash[:status]
8
+ end
9
+
10
+ def success?
11
+ status == 'SUCCESS'
12
+ end
13
+
14
+ def in_progress?
15
+ status == "IN_PROGRESS"
16
+ end
17
+
18
+ def release_hash
19
+ @response_json_hash[:release]
20
+ end
21
+
22
+ def release_id
23
+ release_hash ? release_hash[:id] : nil
24
+ end
25
+ end
@@ -1,5 +1,5 @@
1
1
  module Fastlane
2
2
  module FirebaseAppDistribution
3
- VERSION = "0.1.4"
3
+ VERSION = "0.2.0.pre.1"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +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.1.4
4
+ version: 0.2.0.pre.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stefan Natchev
8
+ - Manny Jimenez
9
+ - Alonso Salas Infante
8
10
  autorequire:
9
11
  bindir: bin
10
12
  cert_chain: []
11
- date: 2019-10-09 00:00:00.000000000 Z
13
+ date: 2020-07-28 00:00:00.000000000 Z
12
14
  dependencies:
13
15
  - !ruby/object:Gem::Dependency
14
16
  name: pry
@@ -139,6 +141,8 @@ dependencies:
139
141
  description:
140
142
  email:
141
143
  - snatchev@google.com
144
+ - mannyjimenez@google.com
145
+ - alonsosi@google.com
142
146
  executables: []
143
147
  extensions: []
144
148
  extra_rdoc_files: []
@@ -147,9 +151,14 @@ files:
147
151
  - README.md
148
152
  - lib/fastlane/plugin/firebase_app_distribution.rb
149
153
  - lib/fastlane/plugin/firebase_app_distribution/actions/firebase_app_distribution_action.rb
154
+ - lib/fastlane/plugin/firebase_app_distribution/actions/firebase_app_distribution_login.rb
155
+ - lib/fastlane/plugin/firebase_app_distribution/client/firebase_app_distribution_api_client.rb
156
+ - lib/fastlane/plugin/firebase_app_distribution/helper/firebase_app_distribution_auth_client.rb
157
+ - lib/fastlane/plugin/firebase_app_distribution/helper/firebase_app_distribution_error_message.rb
150
158
  - lib/fastlane/plugin/firebase_app_distribution/helper/firebase_app_distribution_helper.rb
159
+ - lib/fastlane/plugin/firebase_app_distribution/helper/upload_status_response.rb
151
160
  - lib/fastlane/plugin/firebase_app_distribution/version.rb
152
- homepage: https://github.com/fastlane-community/fastlane-plugin-firebase_app_distribution
161
+ homepage: https://github.com/fastlane/fastlane-plugin-firebase_app_distribution
153
162
  licenses:
154
163
  - MIT
155
164
  metadata: {}
@@ -164,11 +173,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
164
173
  version: '0'
165
174
  required_rubygems_version: !ruby/object:Gem::Requirement
166
175
  requirements:
167
- - - ">="
176
+ - - ">"
168
177
  - !ruby/object:Gem::Version
169
- version: '0'
178
+ version: 1.3.1
170
179
  requirements: []
171
- rubygems_version: 3.0.6
180
+ rubyforge_project:
181
+ rubygems_version: 2.2.5
172
182
  signing_key:
173
183
  specification_version: 4
174
184
  summary: Release your beta builds to Firebase App Distribution. https://firebase.google.com/docs/app-distribution