fastlane-plugin-firebase_app_distribution 0.4.2 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/fastlane/plugin/firebase_app_distribution/actions/firebase_app_distribution_action.rb +22 -3
- data/lib/fastlane/plugin/firebase_app_distribution/actions/firebase_app_distribution_add_testers_action.rb +11 -1
- data/lib/fastlane/plugin/firebase_app_distribution/actions/firebase_app_distribution_create_group_action.rb +87 -0
- data/lib/fastlane/plugin/firebase_app_distribution/actions/firebase_app_distribution_delete_group_action.rb +77 -0
- data/lib/fastlane/plugin/firebase_app_distribution/actions/firebase_app_distribution_get_latest_release.rb +7 -4
- data/lib/fastlane/plugin/firebase_app_distribution/actions/firebase_app_distribution_get_udids.rb +1 -1
- data/lib/fastlane/plugin/firebase_app_distribution/actions/firebase_app_distribution_remove_testers_action.rb +1 -1
- data/lib/fastlane/plugin/firebase_app_distribution/client/firebase_app_distribution_api_client.rb +129 -21
- data/lib/fastlane/plugin/firebase_app_distribution/helper/firebase_app_distribution_auth_client.rb +10 -5
- data/lib/fastlane/plugin/firebase_app_distribution/helper/firebase_app_distribution_error_message.rb +2 -0
- data/lib/fastlane/plugin/firebase_app_distribution/version.rb +1 -1
- metadata +9 -8
- data/lib/fastlane/plugin/firebase_app_distribution/actions/firebase_app_distribution_login.rb +0 -121
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c8c5fed8eb93d2d6c62dee224fb08c366646a91b0ddd38d74689e5c34b0f355b
|
4
|
+
data.tar.gz: 03ee7ef5569e510ae63370cd860ec6f118f6ce5d8771c2f961d9194609232709
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e0b67fbe3ac855aec3dd70be48726d44bcae8eb021a70984ff5274431b0e093c6849ad9ddf64f6186698ffa5701950acc53c602cb48583d520738a1bfa75f6b5
|
7
|
+
data.tar.gz: ec59af9949e4d9086004c63561b2e74a3bf09b9a270b02a12e62d66a322198124c8019724ae7cd33f2f5097615dd9c068f416e3efa5bc48fe4b77e11133b6946
|
data/lib/fastlane/plugin/firebase_app_distribution/actions/firebase_app_distribution_action.rb
CHANGED
@@ -11,6 +11,10 @@ require_relative '../helper/firebase_app_distribution_auth_client'
|
|
11
11
|
## How should we document the usage of release notes?
|
12
12
|
module Fastlane
|
13
13
|
module Actions
|
14
|
+
module SharedValues
|
15
|
+
FIREBASE_APP_DISTRO_RELEASE ||= :FIREBASE_APP_DISTRO_RELEASE
|
16
|
+
end
|
17
|
+
|
14
18
|
class FirebaseAppDistributionAction < Action
|
15
19
|
extend Auth::FirebaseAppDistributionAuthClient
|
16
20
|
extend Helper::FirebaseAppDistributionHelper
|
@@ -48,6 +52,7 @@ module Fastlane
|
|
48
52
|
|
49
53
|
upload_status_response = fad_api_client.upload(app_name, binary_path, platform.to_s, upload_timeout)
|
50
54
|
release_name = upload_status_response.release_name
|
55
|
+
release = upload_status_response.release
|
51
56
|
|
52
57
|
if binary_type == :AAB && aab_info && !aab_info.certs_provided?
|
53
58
|
updated_aab_info = fad_api_client.get_aab_info(app_name)
|
@@ -62,14 +67,19 @@ module Fastlane
|
|
62
67
|
end
|
63
68
|
end
|
64
69
|
|
65
|
-
|
70
|
+
release_notes = release_notes(params)
|
71
|
+
if release_notes.nil? || release_notes.empty?
|
72
|
+
UI.message("⏩ No release notes passed in. Skipping this step.")
|
73
|
+
else
|
74
|
+
release = fad_api_client.update_release_notes(release_name, release_notes)
|
75
|
+
end
|
66
76
|
|
67
77
|
testers = get_value_from_value_or_file(params[:testers], params[:testers_file])
|
68
78
|
groups = get_value_from_value_or_file(params[:groups], params[:groups_file])
|
69
79
|
emails = string_to_array(testers)
|
70
80
|
group_aliases = string_to_array(groups)
|
71
81
|
fad_api_client.distribute(release_name, emails, group_aliases)
|
72
|
-
UI.success("🎉 App Distribution upload finished successfully.")
|
82
|
+
UI.success("🎉 App Distribution upload finished successfully. Setting Actions.lane_context[SharedValues::FIREBASE_APP_DISTRO_RELEASE] to the uploaded release.")
|
73
83
|
|
74
84
|
if upload_status_response.firebase_console_uri
|
75
85
|
UI.message("🔗 View this release in the Firebase console: #{upload_status_response.firebase_console_uri}")
|
@@ -82,6 +92,9 @@ module Fastlane
|
|
82
92
|
if upload_status_response.binary_download_uri
|
83
93
|
UI.message("🔗 Download the release binary (link expires in 1 hour): #{upload_status_response.binary_download_uri}")
|
84
94
|
end
|
95
|
+
|
96
|
+
Actions.lane_context[SharedValues::FIREBASE_APP_DISTRO_RELEASE] = release
|
97
|
+
release
|
85
98
|
end
|
86
99
|
|
87
100
|
def self.description
|
@@ -256,7 +269,7 @@ module Fastlane
|
|
256
269
|
optional: true,
|
257
270
|
type: String),
|
258
271
|
FastlaneCore::ConfigItem.new(key: :firebase_cli_token,
|
259
|
-
description: "Auth token generated using
|
272
|
+
description: "Auth token generated using the Firebase CLI's login:ci command",
|
260
273
|
optional: true,
|
261
274
|
type: String),
|
262
275
|
FastlaneCore::ConfigItem.new(key: :debug,
|
@@ -294,6 +307,12 @@ module Fastlane
|
|
294
307
|
CODE
|
295
308
|
]
|
296
309
|
end
|
310
|
+
|
311
|
+
def self.output
|
312
|
+
[
|
313
|
+
['FIREBASE_APP_DISTRO_RELEASE', 'A hash representing the uploaded release created in Firebase App Distribution']
|
314
|
+
]
|
315
|
+
end
|
297
316
|
end
|
298
317
|
end
|
299
318
|
end
|
@@ -30,6 +30,11 @@ module Fastlane
|
|
30
30
|
|
31
31
|
fad_api_client.add_testers(params[:project_number], emails)
|
32
32
|
|
33
|
+
unless blank?(params[:group_alias])
|
34
|
+
UI.message("⏳ Adding testers to group #{params[:group_alias]}...")
|
35
|
+
fad_api_client.add_testers_to_group(params[:project_number], params[:group_alias], emails)
|
36
|
+
end
|
37
|
+
|
33
38
|
# The add_testers response lists all the testers from the request
|
34
39
|
# regardless of whether or not they were created or if they already
|
35
40
|
# exists so can't get an accurate count of the number of newly created testers
|
@@ -66,12 +71,17 @@ module Fastlane
|
|
66
71
|
description: "Path to a file containing a comma separated list of tester emails to be created. A maximum of 1000 testers can be deleted at a time",
|
67
72
|
optional: true,
|
68
73
|
type: String),
|
74
|
+
FastlaneCore::ConfigItem.new(key: :group_alias,
|
75
|
+
env_name: "FIREBASEAPPDISTRO_ADD_TESTERS_GROUP_ALIAS",
|
76
|
+
description: "Alias of the group to add the specified testers to. The group must already exist. If not specified, testers will not be added to a group",
|
77
|
+
optional: true,
|
78
|
+
type: String),
|
69
79
|
FastlaneCore::ConfigItem.new(key: :service_credentials_file,
|
70
80
|
description: "Path to Google service credentials file",
|
71
81
|
optional: true,
|
72
82
|
type: String),
|
73
83
|
FastlaneCore::ConfigItem.new(key: :firebase_cli_token,
|
74
|
-
description: "Auth token generated using
|
84
|
+
description: "Auth token generated using the Firebase CLI's login:ci command",
|
75
85
|
optional: true,
|
76
86
|
type: String),
|
77
87
|
FastlaneCore::ConfigItem.new(key: :debug,
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'fastlane/action'
|
2
|
+
require 'fastlane_core/ui/ui'
|
3
|
+
|
4
|
+
require_relative '../helper/firebase_app_distribution_helper'
|
5
|
+
require_relative '../helper/firebase_app_distribution_auth_client'
|
6
|
+
|
7
|
+
module Fastlane
|
8
|
+
module Actions
|
9
|
+
class FirebaseAppDistributionCreateGroupAction < Action
|
10
|
+
extend Auth::FirebaseAppDistributionAuthClient
|
11
|
+
extend Helper::FirebaseAppDistributionHelper
|
12
|
+
|
13
|
+
def self.run(params)
|
14
|
+
auth_token = fetch_auth_token(params[:service_credentials_file], params[:firebase_cli_token])
|
15
|
+
fad_api_client = Client::FirebaseAppDistributionApiClient.new(auth_token, params[:debug])
|
16
|
+
|
17
|
+
if blank?(params[:alias])
|
18
|
+
UI.user_error!("Must specify `alias`.")
|
19
|
+
end
|
20
|
+
|
21
|
+
if blank?(params[:display_name])
|
22
|
+
UI.user_error!("Must specify `display_name`.")
|
23
|
+
end
|
24
|
+
|
25
|
+
project_number = params[:project_number]
|
26
|
+
group_alias = params[:alias]
|
27
|
+
display_name = params[:display_name]
|
28
|
+
|
29
|
+
UI.message("⏳ Creating tester group '#{group_alias} (#{display_name})' in project #{project_number}...")
|
30
|
+
|
31
|
+
fad_api_client.create_group(project_number, group_alias, display_name)
|
32
|
+
|
33
|
+
UI.success("✅ Group created successfully.")
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.description
|
37
|
+
"Create a tester group"
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.authors
|
41
|
+
["Garry Jeromson"]
|
42
|
+
end
|
43
|
+
|
44
|
+
# supports markdown.
|
45
|
+
def self.details
|
46
|
+
"Create a tester group"
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.available_options
|
50
|
+
[
|
51
|
+
FastlaneCore::ConfigItem.new(key: :project_number,
|
52
|
+
env_name: "FIREBASEAPPDISTRO_PROJECT_NUMBER",
|
53
|
+
description: "Your Firebase project number. You can find the project number in the Firebase console, on the General Settings page",
|
54
|
+
type: Integer,
|
55
|
+
optional: false),
|
56
|
+
FastlaneCore::ConfigItem.new(key: :alias,
|
57
|
+
env_name: "FIREBASEAPPDISTRO_CREATE_GROUP_ALIAS",
|
58
|
+
description: "Alias of the group to be created",
|
59
|
+
optional: false,
|
60
|
+
type: String),
|
61
|
+
FastlaneCore::ConfigItem.new(key: :display_name,
|
62
|
+
env_name: "FIREBASEAPPDISTRO_CREATE_GROUP_DISPLAY_NAME",
|
63
|
+
description: "Display name for the group to be created",
|
64
|
+
optional: false,
|
65
|
+
type: String),
|
66
|
+
FastlaneCore::ConfigItem.new(key: :service_credentials_file,
|
67
|
+
description: "Path to Google service credentials file",
|
68
|
+
optional: true,
|
69
|
+
type: String),
|
70
|
+
FastlaneCore::ConfigItem.new(key: :firebase_cli_token,
|
71
|
+
description: "Auth token generated using the Firebase CLI's login:ci command",
|
72
|
+
optional: true,
|
73
|
+
type: String),
|
74
|
+
FastlaneCore::ConfigItem.new(key: :debug,
|
75
|
+
description: "Print verbose debug output",
|
76
|
+
optional: true,
|
77
|
+
default_value: false,
|
78
|
+
is_string: false)
|
79
|
+
]
|
80
|
+
end
|
81
|
+
|
82
|
+
def self.is_supported?(platform)
|
83
|
+
true
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'fastlane/action'
|
2
|
+
require 'fastlane_core/ui/ui'
|
3
|
+
|
4
|
+
require_relative '../helper/firebase_app_distribution_helper'
|
5
|
+
require_relative '../helper/firebase_app_distribution_auth_client'
|
6
|
+
|
7
|
+
module Fastlane
|
8
|
+
module Actions
|
9
|
+
class FirebaseAppDistributionDeleteGroupAction < Action
|
10
|
+
extend Auth::FirebaseAppDistributionAuthClient
|
11
|
+
extend Helper::FirebaseAppDistributionHelper
|
12
|
+
|
13
|
+
def self.run(params)
|
14
|
+
auth_token = fetch_auth_token(params[:service_credentials_file], params[:firebase_cli_token])
|
15
|
+
fad_api_client = Client::FirebaseAppDistributionApiClient.new(auth_token, params[:debug])
|
16
|
+
|
17
|
+
if blank?(params[:alias])
|
18
|
+
UI.user_error!("Must specify `alias`.")
|
19
|
+
end
|
20
|
+
|
21
|
+
project_number = params[:project_number]
|
22
|
+
group_alias = params[:alias]
|
23
|
+
|
24
|
+
UI.message("⏳ Deleting tester group '#{group_alias}' in project #{project_number}...")
|
25
|
+
|
26
|
+
fad_api_client.delete_group(project_number, group_alias)
|
27
|
+
|
28
|
+
UI.success("✅ Group deleted successfully.")
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.description
|
32
|
+
"Delete a tester group"
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.authors
|
36
|
+
["Garry Jeromson"]
|
37
|
+
end
|
38
|
+
|
39
|
+
# supports markdown.
|
40
|
+
def self.details
|
41
|
+
"Delete a tester group"
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.available_options
|
45
|
+
[
|
46
|
+
FastlaneCore::ConfigItem.new(key: :project_number,
|
47
|
+
env_name: "FIREBASEAPPDISTRO_PROJECT_NUMBER",
|
48
|
+
description: "Your Firebase project number. You can find the project number in the Firebase console, on the General Settings page",
|
49
|
+
type: Integer,
|
50
|
+
optional: false),
|
51
|
+
FastlaneCore::ConfigItem.new(key: :alias,
|
52
|
+
env_name: "FIREBASEAPPDISTRO_DELETE_GROUP_ALIAS",
|
53
|
+
description: "Alias of the group to be deleted",
|
54
|
+
optional: false,
|
55
|
+
type: String),
|
56
|
+
FastlaneCore::ConfigItem.new(key: :service_credentials_file,
|
57
|
+
description: "Path to Google service credentials file",
|
58
|
+
optional: true,
|
59
|
+
type: String),
|
60
|
+
FastlaneCore::ConfigItem.new(key: :firebase_cli_token,
|
61
|
+
description: "Auth token generated using the Firebase CLI's login:ci command",
|
62
|
+
optional: true,
|
63
|
+
type: String),
|
64
|
+
FastlaneCore::ConfigItem.new(key: :debug,
|
65
|
+
description: "Print verbose debug output",
|
66
|
+
optional: true,
|
67
|
+
default_value: false,
|
68
|
+
is_string: false)
|
69
|
+
]
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.is_supported?(platform)
|
73
|
+
true
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -5,6 +5,9 @@ require_relative '../helper/firebase_app_distribution_helper'
|
|
5
5
|
|
6
6
|
module Fastlane
|
7
7
|
module Actions
|
8
|
+
module SharedValues
|
9
|
+
FIREBASE_APP_DISTRO_LATEST_RELEASE ||= :FIREBASE_APP_DISTRO_LATEST_RELEASE
|
10
|
+
end
|
8
11
|
class FirebaseAppDistributionGetLatestReleaseAction < Action
|
9
12
|
extend Auth::FirebaseAppDistributionAuthClient
|
10
13
|
extend Helper::FirebaseAppDistributionHelper
|
@@ -18,12 +21,12 @@ module Fastlane
|
|
18
21
|
releases = fad_api_client.list_releases(app_name_from_app_id(params[:app]), 1)[:releases] || []
|
19
22
|
if releases.empty?
|
20
23
|
latest_release = nil
|
21
|
-
UI.important("No releases for app #{params[:app]} found in App Distribution. Returning nil and setting Actions.lane_context[
|
24
|
+
UI.important("No releases for app #{params[:app]} found in App Distribution. Returning nil and setting Actions.lane_context[SharedValues::FIREBASE_APP_DISTRO_LATEST_RELEASE].")
|
22
25
|
else
|
23
26
|
latest_release = releases[0]
|
24
|
-
UI.success("✅ Latest release fetched successfully. Returning release and setting Actions.lane_context[
|
27
|
+
UI.success("✅ Latest release fetched successfully. Returning release and setting Actions.lane_context[SharedValues::FIREBASE_APP_DISTRO_LATEST_RELEASE].")
|
25
28
|
end
|
26
|
-
Actions.lane_context[
|
29
|
+
Actions.lane_context[SharedValues::FIREBASE_APP_DISTRO_LATEST_RELEASE] = latest_release
|
27
30
|
return latest_release
|
28
31
|
end
|
29
32
|
|
@@ -49,7 +52,7 @@ module Fastlane
|
|
49
52
|
optional: false,
|
50
53
|
type: String),
|
51
54
|
FastlaneCore::ConfigItem.new(key: :firebase_cli_token,
|
52
|
-
description: "Auth token generated using
|
55
|
+
description: "Auth token generated using Firebase CLI's login:ci command",
|
53
56
|
optional: true,
|
54
57
|
type: String),
|
55
58
|
FastlaneCore::ConfigItem.new(key: :service_credentials_file,
|
data/lib/fastlane/plugin/firebase_app_distribution/actions/firebase_app_distribution_get_udids.rb
CHANGED
@@ -63,7 +63,7 @@ module Fastlane
|
|
63
63
|
optional: false,
|
64
64
|
type: String),
|
65
65
|
FastlaneCore::ConfigItem.new(key: :firebase_cli_token,
|
66
|
-
description: "Auth token generated using
|
66
|
+
description: "Auth token generated using the Firebase CLI's login:ci command",
|
67
67
|
optional: true,
|
68
68
|
type: String),
|
69
69
|
FastlaneCore::ConfigItem.new(key: :service_credentials_file,
|
@@ -68,7 +68,7 @@ module Fastlane
|
|
68
68
|
optional: true,
|
69
69
|
type: String),
|
70
70
|
FastlaneCore::ConfigItem.new(key: :firebase_cli_token,
|
71
|
-
description: "Auth token generated using
|
71
|
+
description: "Auth token generated using the Firebase CLI's login:ci command",
|
72
72
|
optional: true,
|
73
73
|
type: String),
|
74
74
|
FastlaneCore::ConfigItem.new(key: :debug,
|
data/lib/fastlane/plugin/firebase_app_distribution/client/firebase_app_distribution_api_client.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'fastlane_core/ui/ui'
|
2
|
-
require_relative '../actions/firebase_app_distribution_login'
|
3
2
|
require_relative '../client/error_response'
|
4
3
|
require_relative '../client/aab_info'
|
5
4
|
require_relative '../helper/firebase_app_distribution_helper'
|
@@ -59,29 +58,26 @@ module Fastlane
|
|
59
58
|
# release_name - App release resource name, returned by upload_status endpoint
|
60
59
|
# release_notes - String of notes for this release
|
61
60
|
#
|
61
|
+
# Returns a hash of the release
|
62
|
+
#
|
62
63
|
# Throws a user_error if the release_notes are invalid
|
63
64
|
def update_release_notes(release_name, release_notes)
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
begin
|
69
|
-
payload = {
|
70
|
-
name: release_name,
|
71
|
-
releaseNotes: {
|
72
|
-
text: release_notes
|
73
|
-
}
|
65
|
+
payload = {
|
66
|
+
name: release_name,
|
67
|
+
releaseNotes: {
|
68
|
+
text: release_notes
|
74
69
|
}
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
rescue Faraday::ClientError => e
|
81
|
-
error = ErrorResponse.new(e.response)
|
82
|
-
UI.user_error!("#{ErrorMessage::INVALID_RELEASE_NOTES}: #{error.message}")
|
70
|
+
}
|
71
|
+
response = connection.patch(update_release_notes_url(release_name), payload.to_json) do |request|
|
72
|
+
request.headers[AUTHORIZATION] = "Bearer " + @auth_token
|
73
|
+
request.headers[CONTENT_TYPE] = APPLICATION_JSON
|
74
|
+
request.headers[CLIENT_VERSION] = client_version_header_value
|
83
75
|
end
|
84
76
|
UI.success("✅ Posted release notes.")
|
77
|
+
response.body
|
78
|
+
rescue Faraday::ClientError => e
|
79
|
+
error = ErrorResponse.new(e.response)
|
80
|
+
UI.user_error!("#{ErrorMessage::INVALID_RELEASE_NOTES}: #{error.message}")
|
85
81
|
end
|
86
82
|
|
87
83
|
# Get AAB info (Android apps only)
|
@@ -136,7 +132,7 @@ module Fastlane
|
|
136
132
|
# binary_path - Absolute path to your app's aab/apk/ipa file
|
137
133
|
# timeout - The amount of seconds before the upload will timeout, if not completed
|
138
134
|
#
|
139
|
-
# Returns
|
135
|
+
# Returns a `UploadStatusResponse` with the upload is complete.
|
140
136
|
#
|
141
137
|
# Crashes if the number of polling retries exceeds MAX_POLLING_RETRIES or if the binary cannot
|
142
138
|
# be uploaded.
|
@@ -255,6 +251,102 @@ module Fastlane
|
|
255
251
|
UI.user_error!(ErrorMessage::INVALID_PROJECT)
|
256
252
|
end
|
257
253
|
|
254
|
+
# Create tester group
|
255
|
+
#
|
256
|
+
# args
|
257
|
+
# project_number - Firebase project number
|
258
|
+
# group_alias - Alias of the tester group
|
259
|
+
# display_name - Display name of the tester group
|
260
|
+
#
|
261
|
+
def create_group(project_number, group_alias, display_name)
|
262
|
+
payload = { name: "projects/#{project_number}/groups/#{group_alias}",
|
263
|
+
displayName: display_name }
|
264
|
+
response = connection.post(add_tester_group_url(project_number), payload.to_json) do |request|
|
265
|
+
request.params["groupId"] = group_alias
|
266
|
+
request.headers[AUTHORIZATION] = "Bearer " + @auth_token
|
267
|
+
request.headers[CONTENT_TYPE] = APPLICATION_JSON
|
268
|
+
request.headers[CLIENT_VERSION] = client_version_header_value
|
269
|
+
end
|
270
|
+
response.body
|
271
|
+
rescue Faraday::BadRequestError
|
272
|
+
UI.user_error!(ErrorMessage::INVALID_TESTER_GROUP_NAME)
|
273
|
+
rescue Faraday::ResourceNotFound
|
274
|
+
UI.user_error!(ErrorMessage::INVALID_PROJECT)
|
275
|
+
rescue Faraday::ConflictError
|
276
|
+
UI.important("Tester group #{group_alias} already exists.")
|
277
|
+
return {
|
278
|
+
name: "projects/#{project_number}/groups/#{group_alias}"
|
279
|
+
}
|
280
|
+
rescue Faraday::ClientError => e
|
281
|
+
raise e
|
282
|
+
end
|
283
|
+
|
284
|
+
# Add testers to group
|
285
|
+
#
|
286
|
+
# args
|
287
|
+
# project_number - Firebase project number
|
288
|
+
# group_alias - Alias of the tester group
|
289
|
+
# emails - An array of emails to be added to the group.
|
290
|
+
# A maximum of 1000 testers can be added at a time, if creating missing testers is enabled.
|
291
|
+
# create_missing_testers - If true, missing testers will be created and added to the group.
|
292
|
+
#
|
293
|
+
def add_testers_to_group(project_number, group_alias, emails, create_missing_testers = false)
|
294
|
+
payload = { emails: emails,
|
295
|
+
createMissingTesters: create_missing_testers }
|
296
|
+
response = connection.post(add_testers_to_group_url(project_number, group_alias), payload.to_json) do |request|
|
297
|
+
request.headers[AUTHORIZATION] = "Bearer " + @auth_token
|
298
|
+
request.headers[CONTENT_TYPE] = APPLICATION_JSON
|
299
|
+
request.headers[CLIENT_VERSION] = client_version_header_value
|
300
|
+
end
|
301
|
+
response.body
|
302
|
+
rescue Faraday::BadRequestError
|
303
|
+
UI.user_error!(ErrorMessage::INVALID_EMAIL_ADDRESS)
|
304
|
+
rescue Faraday::ResourceNotFound
|
305
|
+
UI.user_error!(ErrorMessage::INVALID_TESTER_GROUP)
|
306
|
+
rescue Faraday::ClientError => e
|
307
|
+
raise e
|
308
|
+
end
|
309
|
+
|
310
|
+
# Remove testers from group
|
311
|
+
#
|
312
|
+
# args
|
313
|
+
# project_number - Firebase project number
|
314
|
+
# group_alias - Alias of the tester group
|
315
|
+
# emails - An array of emails to be removed from the group.
|
316
|
+
#
|
317
|
+
def remove_testers_from_group(project_number, group_alias, emails)
|
318
|
+
payload = { emails: emails }
|
319
|
+
response = connection.post(remove_testers_from_group_url(project_number, group_alias), payload.to_json) do |request|
|
320
|
+
request.headers[AUTHORIZATION] = "Bearer " + @auth_token
|
321
|
+
request.headers[CONTENT_TYPE] = APPLICATION_JSON
|
322
|
+
request.headers[CLIENT_VERSION] = client_version_header_value
|
323
|
+
end
|
324
|
+
response.body
|
325
|
+
rescue Faraday::BadRequestError
|
326
|
+
UI.user_error!(ErrorMessage::INVALID_EMAIL_ADDRESS)
|
327
|
+
rescue Faraday::ResourceNotFound
|
328
|
+
UI.user_error!(ErrorMessage::INVALID_TESTER_GROUP)
|
329
|
+
rescue Faraday::ClientError => e
|
330
|
+
raise e
|
331
|
+
end
|
332
|
+
|
333
|
+
# Delete tester group
|
334
|
+
#
|
335
|
+
# args
|
336
|
+
# project_number - Firebase project number
|
337
|
+
# group_alias - Alias of the tester group
|
338
|
+
#
|
339
|
+
def delete_group(project_number, group_alias)
|
340
|
+
response = connection.delete(delete_tester_group_url(project_number, group_alias)) do |request|
|
341
|
+
request.headers[AUTHORIZATION] = "Bearer " + @auth_token
|
342
|
+
request.headers[CONTENT_TYPE] = APPLICATION_JSON
|
343
|
+
request.headers[CLIENT_VERSION] = client_version_header_value
|
344
|
+
end
|
345
|
+
response.body
|
346
|
+
rescue Faraday::ResourceNotFound
|
347
|
+
UI.user_error!(ErrorMessage::INVALID_TESTER_GROUP)
|
348
|
+
end
|
349
|
+
|
258
350
|
# List releases
|
259
351
|
#
|
260
352
|
# args
|
@@ -273,7 +365,7 @@ module Fastlane
|
|
273
365
|
UI.user_error!("#{ErrorMessage::INVALID_APP_ID}: #{app_name}")
|
274
366
|
end
|
275
367
|
|
276
|
-
|
368
|
+
response.body
|
277
369
|
end
|
278
370
|
|
279
371
|
private
|
@@ -326,6 +418,22 @@ module Fastlane
|
|
326
418
|
"/v1/projects/#{project_number}/testers:batchRemove"
|
327
419
|
end
|
328
420
|
|
421
|
+
def add_tester_group_url(project_number)
|
422
|
+
"/v1/projects/#{project_number}/groups"
|
423
|
+
end
|
424
|
+
|
425
|
+
def delete_tester_group_url(project_number, group_alias)
|
426
|
+
"/v1/projects/#{project_number}/groups/#{group_alias}"
|
427
|
+
end
|
428
|
+
|
429
|
+
def add_testers_to_group_url(project_number, group_alias)
|
430
|
+
"/v1/projects/#{project_number}/groups/#{group_alias}:batchJoin"
|
431
|
+
end
|
432
|
+
|
433
|
+
def remove_testers_from_group_url(project_number, group_alias)
|
434
|
+
"/v1/projects/#{project_number}/groups/#{group_alias}:batchLeave"
|
435
|
+
end
|
436
|
+
|
329
437
|
def connection
|
330
438
|
@connection ||= Faraday.new(url: BASE_URL) do |conn|
|
331
439
|
conn.response(:json, parser_options: { symbolize_names: true })
|
data/lib/fastlane/plugin/firebase_app_distribution/helper/firebase_app_distribution_auth_client.rb
CHANGED
@@ -6,6 +6,12 @@ module Fastlane
|
|
6
6
|
TOKEN_CREDENTIAL_URI = "https://oauth2.googleapis.com/token"
|
7
7
|
REDACTION_EXPOSED_LENGTH = 5
|
8
8
|
REDACTION_CHARACTER = "X"
|
9
|
+
SCOPE = "https://www.googleapis.com/auth/cloud-platform"
|
10
|
+
|
11
|
+
# In this type of application, the client secret is not treated as a secret.
|
12
|
+
# See: https://developers.google.com/identity/protocols/OAuth2InstalledApp
|
13
|
+
CLIENT_ID = "563584335869-fgrhgmd47bqnekij5i8b5pr03ho849e6.apps.googleusercontent.com"
|
14
|
+
CLIENT_SECRET = "j9iVZfS8kkCEFUPaAeJV0sAi"
|
9
15
|
|
10
16
|
# Returns the auth token for any of the auth methods (Firebase CLI token,
|
11
17
|
# Google service account, firebase-tools). To ensure that a specific
|
@@ -13,8 +19,7 @@ module Fastlane
|
|
13
19
|
#
|
14
20
|
# args
|
15
21
|
# google_service_path - Absolute path to the Google service account file
|
16
|
-
# firebase_cli_token -
|
17
|
-
# CI environment
|
22
|
+
# firebase_cli_token - Refresh token
|
18
23
|
# debug - Whether to enable debug-level logging
|
19
24
|
#
|
20
25
|
# env variables
|
@@ -74,8 +79,8 @@ module Fastlane
|
|
74
79
|
def firebase_token(refresh_token, debug)
|
75
80
|
client = Signet::OAuth2::Client.new(
|
76
81
|
token_credential_uri: TOKEN_CREDENTIAL_URI,
|
77
|
-
client_id:
|
78
|
-
client_secret:
|
82
|
+
client_id: CLIENT_ID,
|
83
|
+
client_secret: CLIENT_SECRET,
|
79
84
|
refresh_token: refresh_token
|
80
85
|
)
|
81
86
|
client.fetch_access_token!
|
@@ -94,7 +99,7 @@ module Fastlane
|
|
94
99
|
def service_account(google_service_path, debug)
|
95
100
|
service_account_credentials = Google::Auth::ServiceAccountCredentials.make_creds(
|
96
101
|
json_key_io: File.open(google_service_path),
|
97
|
-
scope:
|
102
|
+
scope: SCOPE
|
98
103
|
)
|
99
104
|
service_account_credentials.fetch_access_token!["access_token"]
|
100
105
|
rescue Errno::ENOENT
|
data/lib/fastlane/plugin/firebase_app_distribution/helper/firebase_app_distribution_error_message.rb
CHANGED
@@ -13,6 +13,8 @@ module ErrorMessage
|
|
13
13
|
INVALID_PROJECT = "App Distribution could not find your Firebase project. Make sure to onboard an app in your project by pressing the \"Get started\" button on the App Distribution page in the Firebase console: https://console.firebase.google.com/project/_/appdistribution."
|
14
14
|
INVALID_PATH = "Could not read content from"
|
15
15
|
INVALID_TESTERS = "Could not enable access for testers. Check that the tester emails are formatted correctly, the groups exist and you are using group aliases (not group names) for specifying groups."
|
16
|
+
INVALID_TESTER_GROUP = "App Distribution could not find your tester group. Make sure that it exists before trying to add testers, and that the group alias is specified correctly."
|
17
|
+
INVALID_TESTER_GROUP_NAME = "The tester group name should be 4-63 characters, and valid characters are /[a-z][0-9]-/."
|
16
18
|
INVALID_RELEASE_NOTES = "Failed to add release notes"
|
17
19
|
SERVICE_CREDENTIALS_ERROR = "App Distribution could not generate credentials from the service credentials file specified"
|
18
20
|
PLAY_ACCOUNT_NOT_LINKED = "This project is not linked to a Google Play account."
|
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.
|
4
|
+
version: 0.6.0
|
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: 2023-
|
13
|
+
date: 2023-06-05 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
|
@@ -153,9 +153,10 @@ files:
|
|
153
153
|
- lib/fastlane/plugin/firebase_app_distribution.rb
|
154
154
|
- lib/fastlane/plugin/firebase_app_distribution/actions/firebase_app_distribution_action.rb
|
155
155
|
- lib/fastlane/plugin/firebase_app_distribution/actions/firebase_app_distribution_add_testers_action.rb
|
156
|
+
- lib/fastlane/plugin/firebase_app_distribution/actions/firebase_app_distribution_create_group_action.rb
|
157
|
+
- lib/fastlane/plugin/firebase_app_distribution/actions/firebase_app_distribution_delete_group_action.rb
|
156
158
|
- lib/fastlane/plugin/firebase_app_distribution/actions/firebase_app_distribution_get_latest_release.rb
|
157
159
|
- lib/fastlane/plugin/firebase_app_distribution/actions/firebase_app_distribution_get_udids.rb
|
158
|
-
- lib/fastlane/plugin/firebase_app_distribution/actions/firebase_app_distribution_login.rb
|
159
160
|
- lib/fastlane/plugin/firebase_app_distribution/actions/firebase_app_distribution_remove_testers_action.rb
|
160
161
|
- lib/fastlane/plugin/firebase_app_distribution/client/aab_info.rb
|
161
162
|
- lib/fastlane/plugin/firebase_app_distribution/client/error_response.rb
|
@@ -169,7 +170,7 @@ homepage: https://github.com/fastlane/fastlane-plugin-firebase_app_distribution
|
|
169
170
|
licenses:
|
170
171
|
- MIT
|
171
172
|
metadata: {}
|
172
|
-
post_install_message:
|
173
|
+
post_install_message:
|
173
174
|
rdoc_options: []
|
174
175
|
require_paths:
|
175
176
|
- lib
|
@@ -184,8 +185,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
184
185
|
- !ruby/object:Gem::Version
|
185
186
|
version: '0'
|
186
187
|
requirements: []
|
187
|
-
rubygems_version: 3.
|
188
|
-
signing_key:
|
188
|
+
rubygems_version: 3.4.10
|
189
|
+
signing_key:
|
189
190
|
specification_version: 4
|
190
191
|
summary: Release your beta builds to Firebase App Distribution. https://firebase.google.com/docs/app-distribution
|
191
192
|
test_files: []
|
data/lib/fastlane/plugin/firebase_app_distribution/actions/firebase_app_distribution_login.rb
DELETED
@@ -1,121 +0,0 @@
|
|
1
|
-
require 'googleauth'
|
2
|
-
require "fileutils"
|
3
|
-
|
4
|
-
module Fastlane
|
5
|
-
module Actions
|
6
|
-
class FirebaseAppDistributionLoginAction < Action
|
7
|
-
SCOPE = "https://www.googleapis.com/auth/cloud-platform"
|
8
|
-
|
9
|
-
# In this type of application, the client secret is not treated as a secret.
|
10
|
-
# See: https://developers.google.com/identity/protocols/OAuth2InstalledApp
|
11
|
-
CLIENT_ID = "563584335869-fgrhgmd47bqnekij5i8b5pr03ho849e6.apps.googleusercontent.com"
|
12
|
-
CLIENT_SECRET = "j9iVZfS8kkCEFUPaAeJV0sAi"
|
13
|
-
|
14
|
-
def self.run(params)
|
15
|
-
callback_uri = "http://localhost:#{params[:port]}"
|
16
|
-
client_id = Google::Auth::ClientId.new(CLIENT_ID, CLIENT_SECRET)
|
17
|
-
authorizer = Google::Auth::UserAuthorizer.new(client_id, SCOPE, nil, callback_uri)
|
18
|
-
|
19
|
-
# Create an anti-forgery state token as described here:
|
20
|
-
# https://developers.google.com/identity/protocols/OpenIDConnect#createxsrftoken
|
21
|
-
state = SecureRandom.hex(16)
|
22
|
-
url = authorizer.get_authorization_url(state: state)
|
23
|
-
|
24
|
-
UI.message("Open the following address in your browser and sign in with your Google account:")
|
25
|
-
UI.message(url)
|
26
|
-
|
27
|
-
response_params = get_authorization_code(params[:port])
|
28
|
-
|
29
|
-
# Confirm that the state in the response matches the state token used to
|
30
|
-
# generate the authorization URL.
|
31
|
-
unless state == response_params['state'][0]
|
32
|
-
UI.crash!('An error has occurred. The state parameter in the authorization response does not match the expected state, which could mean that a malicious attacker is trying to make a login request.')
|
33
|
-
end
|
34
|
-
|
35
|
-
user_credentials = authorizer.get_credentials_from_code(
|
36
|
-
code: response_params['code'][0]
|
37
|
-
)
|
38
|
-
UI.success("Set the refresh token as the FIREBASE_TOKEN environment variable")
|
39
|
-
UI.success("Refresh Token: #{user_credentials.refresh_token}")
|
40
|
-
rescue => error
|
41
|
-
UI.error(error.to_s)
|
42
|
-
UI.crash!("An error has occurred, please login again.")
|
43
|
-
end
|
44
|
-
|
45
|
-
def self.get_authorization_code(port)
|
46
|
-
begin
|
47
|
-
server = TCPServer.open(port)
|
48
|
-
rescue Errno::EADDRINUSE => error
|
49
|
-
UI.error(error.to_s)
|
50
|
-
UI.crash!("Port #{port} is in use. Please specify a different one using the port parameter.")
|
51
|
-
end
|
52
|
-
client = server.accept
|
53
|
-
callback_request = client.readline
|
54
|
-
# Use a regular expression to extract the request line from the first line of
|
55
|
-
# the callback request, e.g.:
|
56
|
-
# GET /?code=AUTH_CODE&state=XYZ&scope=... HTTP/1.1
|
57
|
-
matcher = /GET +([^ ]+)/.match(callback_request)
|
58
|
-
response_params = CGI.parse(URI.parse(matcher[1]).query) unless matcher.nil?
|
59
|
-
|
60
|
-
client.puts("HTTP/1.1 200 OK")
|
61
|
-
client.puts("Content-Type: text/html")
|
62
|
-
client.puts("")
|
63
|
-
client.puts("<b>")
|
64
|
-
if response_params['code'].nil?
|
65
|
-
client.puts("Failed to retrieve authorization code.")
|
66
|
-
else
|
67
|
-
client.puts("Authorization code was successfully retrieved.")
|
68
|
-
end
|
69
|
-
client.puts("</b>")
|
70
|
-
client.puts("<p>Please check the console output.</p>")
|
71
|
-
client.close
|
72
|
-
|
73
|
-
return response_params
|
74
|
-
end
|
75
|
-
|
76
|
-
#####################################################
|
77
|
-
# @!group Documentation
|
78
|
-
#####################################################
|
79
|
-
|
80
|
-
def self.description
|
81
|
-
"Authenticate with Firebase App Distribution using a Google account."
|
82
|
-
end
|
83
|
-
|
84
|
-
def self.details
|
85
|
-
"Log in to Firebase App Distribution using a Google account to generate an authentication "\
|
86
|
-
"token. This token is stored within an environment variable and used to authenticate with your Firebase project. "\
|
87
|
-
"See https://firebase.google.com/docs/app-distribution/ios/distribute-fastlane for more information."
|
88
|
-
end
|
89
|
-
|
90
|
-
def self.authors
|
91
|
-
["Manny Jimenez Github: mannyjimenez0810, Alonso Salas Infante Github: alonsosalasinfante"]
|
92
|
-
end
|
93
|
-
|
94
|
-
def self.is_supported?(platform)
|
95
|
-
[:ios, :android].include?(platform)
|
96
|
-
end
|
97
|
-
|
98
|
-
def self.available_options
|
99
|
-
[
|
100
|
-
FastlaneCore::ConfigItem.new(key: :port,
|
101
|
-
env_name: "FIREBASEAPPDISTRO_LOGIN_PORT",
|
102
|
-
description: "Port for the local web server which receives the response from Google's authorization server",
|
103
|
-
default_value: "8081",
|
104
|
-
optional: true,
|
105
|
-
type: String)
|
106
|
-
|
107
|
-
]
|
108
|
-
end
|
109
|
-
|
110
|
-
def self.category
|
111
|
-
:deprecated
|
112
|
-
end
|
113
|
-
|
114
|
-
def self.deprecated_notes
|
115
|
-
"The firebase_app_distribution_login task is deprecated and will be removed in Q1 2023. See "\
|
116
|
-
"https://firebase.google.com/docs/app-distribution/android/distribute-gradle#authenticate "\
|
117
|
-
"for more information on alternative ways to authenticate."
|
118
|
-
end
|
119
|
-
end
|
120
|
-
end
|
121
|
-
end
|