fastlane-plugin-firebase_app_distribution 0.1.4 → 0.2.0.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
- 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