fastlane-plugin-appcircle_testing_distribution 0.4.3.beta.2 → 0.4.3.beta.3
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/README.md +18 -0
- data/lib/fastlane/plugin/appcircle_testing_distribution/actions/appcircle_testing_distribution_action.rb +35 -16
- data/lib/fastlane/plugin/appcircle_testing_distribution/helper/TDAuthService.rb +6 -6
- data/lib/fastlane/plugin/appcircle_testing_distribution/helper/TDUploadService.rb +22 -20
- data/lib/fastlane/plugin/appcircle_testing_distribution/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d29253d3bd644428e3c3403ec7de545a6570cf3e2b470c58ba50ddb6c211da9d
|
|
4
|
+
data.tar.gz: 3e8298d2f5d547d5891a9f5d34a043c05fdfedf2c5c3c2d66f43def751a372d0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f5d216ec25e3c4162fcad0da1bcd5c2dc28fd9711d973d987c3841b1473f903b83fa2b827bcc894082b1006ce30c811ef6599138816d5455970599418ab8ffa6
|
|
7
|
+
data.tar.gz: 0c4280025c48eda9e4b54fdbe44bd7f839cca35bdd2439cd5ab7b0784a0f7d43d6a908df98617891b8f64e489078fb107b63954dc3cf8c80f81059b0cc2204b0
|
data/README.md
CHANGED
|
@@ -104,6 +104,24 @@ Provide **either** `personalAPIToken` **or** `personalAccessKey` — not both. I
|
|
|
104
104
|
- `appPath`: Indicates the file path to the application package that will be uploaded to Appcircle Testing Distribution Profile.
|
|
105
105
|
- `message`: Your message to testers, ensuring they receive important updates and information regarding the application.
|
|
106
106
|
|
|
107
|
+
### Self-Hosted Appcircle
|
|
108
|
+
|
|
109
|
+
If you run a self-hosted Appcircle installation, point the plugin to your own endpoints. Both parameters are optional and default to the Appcircle cloud, so existing cloud users do not need to set them.
|
|
110
|
+
|
|
111
|
+
- `authEndpoint` (optional): Authentication endpoint URL. Defaults to `https://auth.appcircle.io`.
|
|
112
|
+
- `apiEndpoint` (optional): API endpoint URL. Defaults to `https://api.appcircle.io`.
|
|
113
|
+
|
|
114
|
+
```ruby
|
|
115
|
+
appcircle_testing_distribution(
|
|
116
|
+
personalAPIToken: ENV["AC_PERSONAL_API_TOKEN"],
|
|
117
|
+
authEndpoint: "https://auth.my-appcircle.example.com",
|
|
118
|
+
apiEndpoint: "https://api.my-appcircle.example.com",
|
|
119
|
+
profileName: ENV["AC_PROFILE_NAME"],
|
|
120
|
+
appPath: ENV["AC_APP_PATH"],
|
|
121
|
+
message: ENV["AC_MESSAGE"]
|
|
122
|
+
)
|
|
123
|
+
```
|
|
124
|
+
|
|
107
125
|
## Further Details
|
|
108
126
|
|
|
109
127
|
For more information please refer to the documentation.
|
|
@@ -33,6 +33,9 @@ module Fastlane
|
|
|
33
33
|
#
|
|
34
34
|
appPath = params[:appPath]
|
|
35
35
|
message = params[:message]
|
|
36
|
+
#
|
|
37
|
+
authEndpoint = params[:authEndpoint]
|
|
38
|
+
apiEndpoint = params[:apiEndpoint]
|
|
36
39
|
|
|
37
40
|
profileAuthType = AUTH_TYPE_MAPPING[profileAuthType] # map input to API values
|
|
38
41
|
|
|
@@ -46,23 +49,25 @@ module Fastlane
|
|
|
46
49
|
# Auth
|
|
47
50
|
authToken = self.ac_login(personal_api_token: personalAPIToken,
|
|
48
51
|
personal_access_key: personalAccessKey,
|
|
49
|
-
sub_organization_name: subOrganizationName
|
|
52
|
+
sub_organization_name: subOrganizationName,
|
|
53
|
+
auth_endpoint: authEndpoint,
|
|
54
|
+
api_endpoint: apiEndpoint)
|
|
50
55
|
|
|
51
56
|
# Get or create profile
|
|
52
|
-
profileId = self.ac_get_or_create_profile(authToken, profileName, createProfileIfNotExists, profileCreationSettings, profileAuthType, profileUsername, profilePassword, profileTestingGroupNames)
|
|
57
|
+
profileId = self.ac_get_or_create_profile(authToken, profileName, createProfileIfNotExists, profileCreationSettings, profileAuthType, profileUsername, profilePassword, profileTestingGroupNames, apiEndpoint)
|
|
53
58
|
|
|
54
59
|
# Upload package
|
|
55
|
-
self.ac_upload(authToken, appPath, profileId, profileName, message)
|
|
60
|
+
self.ac_upload(authToken, appPath, profileId, profileName, message, apiEndpoint)
|
|
56
61
|
end
|
|
57
62
|
|
|
58
|
-
def self.ac_login(personal_api_token:, personal_access_key:, sub_organization_name:)
|
|
63
|
+
def self.ac_login(personal_api_token:, personal_access_key:, sub_organization_name:, auth_endpoint:, api_endpoint:)
|
|
59
64
|
begin
|
|
60
65
|
token = ''
|
|
61
66
|
|
|
62
67
|
if personal_access_key
|
|
63
|
-
user = TDAuthService.get_ac_token_with_personal_access_key(personal_access_key: personal_access_key)
|
|
68
|
+
user = TDAuthService.get_ac_token_with_personal_access_key(personal_access_key: personal_access_key, auth_endpoint: auth_endpoint)
|
|
64
69
|
else
|
|
65
|
-
user = TDAuthService.get_ac_token(pat: personal_api_token)
|
|
70
|
+
user = TDAuthService.get_ac_token(pat: personal_api_token, auth_endpoint: auth_endpoint)
|
|
66
71
|
end
|
|
67
72
|
UI.success("Login is successful.")
|
|
68
73
|
token = user.accessToken
|
|
@@ -71,8 +76,8 @@ module Fastlane
|
|
|
71
76
|
if personal_access_key
|
|
72
77
|
UI.important("Warning: subOrganizationName is currently only supported with personalAPIToken auth. Ignoring sub-organization switch for Personal Access Key login.")
|
|
73
78
|
else
|
|
74
|
-
organization_id = TDAuthService.get_organization_id(access_token: token, name: sub_organization_name)
|
|
75
|
-
user = TDAuthService.get_ac_token(pat: personal_api_token, sub_organization_id: organization_id)
|
|
79
|
+
organization_id = TDAuthService.get_organization_id(access_token: token, name: sub_organization_name, api_endpoint: api_endpoint)
|
|
80
|
+
user = TDAuthService.get_ac_token(pat: personal_api_token, sub_organization_id: organization_id, auth_endpoint: auth_endpoint)
|
|
76
81
|
UI.message("Switched to sub-organization: #{sub_organization_name}")
|
|
77
82
|
token = user.accessToken
|
|
78
83
|
end
|
|
@@ -85,9 +90,9 @@ module Fastlane
|
|
|
85
90
|
end
|
|
86
91
|
end
|
|
87
92
|
|
|
88
|
-
def self.ac_get_or_create_profile(authToken, profileName, createProfileIfNotExists, profileCreationSettings, profileAuthType, profileUsername, profilePassword, profileTestingGroupNames)
|
|
93
|
+
def self.ac_get_or_create_profile(authToken, profileName, createProfileIfNotExists, profileCreationSettings, profileAuthType, profileUsername, profilePassword, profileTestingGroupNames, apiEndpoint)
|
|
89
94
|
begin
|
|
90
|
-
profileId = TDUploadService.get_profile_id(authToken, profileName)
|
|
95
|
+
profileId = TDUploadService.get_profile_id(authToken, profileName, apiEndpoint)
|
|
91
96
|
|
|
92
97
|
if profileId
|
|
93
98
|
UI.message("Profile '#{profileName}' found with ID: #{profileId}.")
|
|
@@ -97,7 +102,7 @@ module Fastlane
|
|
|
97
102
|
UI.user_error!("Error: Profile '#{profileName}' not found. The option 'createProfileIfNotExists' is set to false, so a new profile was not created. To automatically create a new profile when it doesn't exist, set 'createProfileIfNotExists' to true.")
|
|
98
103
|
elsif profileId.nil? && createProfileIfNotExists
|
|
99
104
|
UI.message("Profile '#{profileName}' not found. Creating the new profile...")
|
|
100
|
-
profileId = TDUploadService.create_profile(authToken, profileName, profileAuthType, profileUsername, profilePassword, profileTestingGroupNames)
|
|
105
|
+
profileId = TDUploadService.create_profile(authToken, profileName, profileAuthType, profileUsername, profilePassword, profileTestingGroupNames, apiEndpoint)
|
|
101
106
|
end
|
|
102
107
|
|
|
103
108
|
return profileId
|
|
@@ -107,11 +112,11 @@ module Fastlane
|
|
|
107
112
|
end
|
|
108
113
|
end
|
|
109
114
|
|
|
110
|
-
def self.ac_upload(token, appPath, profileID, profileName, message)
|
|
115
|
+
def self.ac_upload(token, appPath, profileID, profileName, message, apiEndpoint)
|
|
111
116
|
begin
|
|
112
117
|
UI.message("Upload started.")
|
|
113
|
-
response = TDUploadService.upload_artifact(token: token, message: message, app: appPath, dist_profile_id: profileID)
|
|
114
|
-
result = self.checkTaskStatus(token, response['taskId'])
|
|
118
|
+
response = TDUploadService.upload_artifact(token: token, message: message, app: appPath, dist_profile_id: profileID, api_endpoint: apiEndpoint)
|
|
119
|
+
result = self.checkTaskStatus(token, response['taskId'], apiEndpoint)
|
|
115
120
|
|
|
116
121
|
if result
|
|
117
122
|
UI.success("#{appPath} uploaded to profile '#{profileName}' successfully 🎉")
|
|
@@ -122,8 +127,8 @@ module Fastlane
|
|
|
122
127
|
end
|
|
123
128
|
end
|
|
124
129
|
|
|
125
|
-
def self.checkTaskStatus(authToken, taskId)
|
|
126
|
-
uri = URI.parse("
|
|
130
|
+
def self.checkTaskStatus(authToken, taskId, apiEndpoint)
|
|
131
|
+
uri = URI.parse("#{apiEndpoint}/task/v1/tasks/#{taskId}")
|
|
127
132
|
|
|
128
133
|
check_interval = 1
|
|
129
134
|
# timeout = 2 * 60 * 60 # 2 hours in seconds
|
|
@@ -197,6 +202,20 @@ module Fastlane
|
|
|
197
202
|
optional: true,
|
|
198
203
|
type: String),
|
|
199
204
|
|
|
205
|
+
FastlaneCore::ConfigItem.new(key: :authEndpoint,
|
|
206
|
+
env_name: "AC_AUTH_ENDPOINT",
|
|
207
|
+
description: "Optional: Authentication endpoint URL for self-hosted Appcircle installations. Defaults to the Appcircle cloud",
|
|
208
|
+
optional: true,
|
|
209
|
+
default_value: "https://auth.appcircle.io",
|
|
210
|
+
type: String),
|
|
211
|
+
|
|
212
|
+
FastlaneCore::ConfigItem.new(key: :apiEndpoint,
|
|
213
|
+
env_name: "AC_API_ENDPOINT",
|
|
214
|
+
description: "Optional: API endpoint URL for self-hosted Appcircle installations. Defaults to the Appcircle cloud",
|
|
215
|
+
optional: true,
|
|
216
|
+
default_value: "https://api.appcircle.io",
|
|
217
|
+
type: String),
|
|
218
|
+
|
|
200
219
|
FastlaneCore::ConfigItem.new(key: :profileName,
|
|
201
220
|
env_name: "AC_PROFILE_NAME",
|
|
202
221
|
description: "Enter the profile name of the Appcircle testing distribution profile. This name uniquely identifies the profile under which your applications will be distributed",
|
|
@@ -13,8 +13,8 @@ class UserResponse
|
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
module TDAuthService
|
|
16
|
-
def self.get_ac_token(pat:, sub_organization_id: nil)
|
|
17
|
-
endpoint_url =
|
|
16
|
+
def self.get_ac_token(pat:, sub_organization_id: nil, auth_endpoint: 'https://auth.appcircle.io')
|
|
17
|
+
endpoint_url = "#{auth_endpoint}/auth/v2/token"
|
|
18
18
|
uri = URI(endpoint_url)
|
|
19
19
|
|
|
20
20
|
# Create HTTP request
|
|
@@ -46,8 +46,8 @@ module TDAuthService
|
|
|
46
46
|
end
|
|
47
47
|
end
|
|
48
48
|
|
|
49
|
-
def self.get_organization_id(access_token:, name:)
|
|
50
|
-
endpoint_url =
|
|
49
|
+
def self.get_organization_id(access_token:, name:, api_endpoint: 'https://api.appcircle.io')
|
|
50
|
+
endpoint_url = "#{api_endpoint}/identity/v1/organizations"
|
|
51
51
|
uri = URI(endpoint_url)
|
|
52
52
|
|
|
53
53
|
# Create HTTP request
|
|
@@ -74,8 +74,8 @@ module TDAuthService
|
|
|
74
74
|
end
|
|
75
75
|
end
|
|
76
76
|
|
|
77
|
-
def self.get_ac_token_with_personal_access_key(personal_access_key:)
|
|
78
|
-
endpoint_url =
|
|
77
|
+
def self.get_ac_token_with_personal_access_key(personal_access_key:, auth_endpoint: 'https://auth.appcircle.io')
|
|
78
|
+
endpoint_url = "#{auth_endpoint}/auth/v1/token"
|
|
79
79
|
uri = URI(endpoint_url)
|
|
80
80
|
|
|
81
81
|
# Create HTTP request
|
|
@@ -8,12 +8,12 @@ BASE_URL = "https://api.appcircle.io"
|
|
|
8
8
|
module TDUploadService
|
|
9
9
|
UI = FastlaneCore::UI
|
|
10
10
|
|
|
11
|
-
def self.upload_artifact(token:, message:, app:, dist_profile_id:)
|
|
11
|
+
def self.upload_artifact(token:, message:, app:, dist_profile_id:, api_endpoint: BASE_URL)
|
|
12
12
|
file_path = app
|
|
13
13
|
file_name = File.basename(file_path)
|
|
14
14
|
file_size = File.size(file_path)
|
|
15
15
|
|
|
16
|
-
upload_info_url = "#{
|
|
16
|
+
upload_info_url = "#{api_endpoint}/distribution/v1/profiles/#{dist_profile_id}/app-versions"
|
|
17
17
|
headers = {
|
|
18
18
|
Authorization: "Bearer #{token}",
|
|
19
19
|
accept: 'application/json'
|
|
@@ -53,7 +53,7 @@ module TDUploadService
|
|
|
53
53
|
raise "File upload failed."
|
|
54
54
|
end
|
|
55
55
|
|
|
56
|
-
commit_url = "#{
|
|
56
|
+
commit_url = "#{api_endpoint}/distribution/v1/profiles/#{dist_profile_id}/app-versions"
|
|
57
57
|
uri = URI(commit_url)
|
|
58
58
|
uri.query = URI.encode_www_form({ action: 'commitFileUpload' })
|
|
59
59
|
|
|
@@ -87,8 +87,8 @@ module TDUploadService
|
|
|
87
87
|
end
|
|
88
88
|
end
|
|
89
89
|
|
|
90
|
-
def self.get_distribution_profiles(auth_token:)
|
|
91
|
-
url = "#{
|
|
90
|
+
def self.get_distribution_profiles(auth_token:, api_endpoint: BASE_URL)
|
|
91
|
+
url = "#{api_endpoint}/distribution/v2/profiles"
|
|
92
92
|
|
|
93
93
|
# Set up the headers with authentication
|
|
94
94
|
headers = {
|
|
@@ -106,8 +106,8 @@ module TDUploadService
|
|
|
106
106
|
end
|
|
107
107
|
end
|
|
108
108
|
|
|
109
|
-
def self.get_testing_groups(auth_token:)
|
|
110
|
-
url = "#{
|
|
109
|
+
def self.get_testing_groups(auth_token:, api_endpoint: BASE_URL)
|
|
110
|
+
url = "#{api_endpoint}/distribution/v2/testing-groups"
|
|
111
111
|
|
|
112
112
|
# Set up the headers with authentication
|
|
113
113
|
headers = {
|
|
@@ -125,8 +125,8 @@ module TDUploadService
|
|
|
125
125
|
end
|
|
126
126
|
end
|
|
127
127
|
|
|
128
|
-
def self.create_distribution_profile(name:, auth_token:)
|
|
129
|
-
url = "#{
|
|
128
|
+
def self.create_distribution_profile(name:, auth_token:, api_endpoint: BASE_URL)
|
|
129
|
+
url = "#{api_endpoint}/distribution/v2/profiles"
|
|
130
130
|
headers = {
|
|
131
131
|
Authorization: "Bearer #{auth_token}",
|
|
132
132
|
content_type: :json,
|
|
@@ -146,8 +146,8 @@ module TDUploadService
|
|
|
146
146
|
end
|
|
147
147
|
end
|
|
148
148
|
|
|
149
|
-
def self.update_distribution_profile(profile_id:, auth_type:, username:, password:, testing_group_ids:, auth_token:)
|
|
150
|
-
url = "#{
|
|
149
|
+
def self.update_distribution_profile(profile_id:, auth_type:, username:, password:, testing_group_ids:, auth_token:, api_endpoint: BASE_URL)
|
|
150
|
+
url = "#{api_endpoint}/distribution/v2/profiles/#{profile_id}"
|
|
151
151
|
headers = {
|
|
152
152
|
Authorization: "Bearer #{auth_token}",
|
|
153
153
|
content_type: :json,
|
|
@@ -179,11 +179,11 @@ module TDUploadService
|
|
|
179
179
|
end
|
|
180
180
|
end
|
|
181
181
|
|
|
182
|
-
def self.get_profile_id(authToken, profileName)
|
|
182
|
+
def self.get_profile_id(authToken, profileName, api_endpoint = BASE_URL)
|
|
183
183
|
profileId = nil
|
|
184
184
|
|
|
185
185
|
begin
|
|
186
|
-
profiles = TDUploadService.get_distribution_profiles(auth_token: authToken)
|
|
186
|
+
profiles = TDUploadService.get_distribution_profiles(auth_token: authToken, api_endpoint: api_endpoint)
|
|
187
187
|
profiles.each do |profile|
|
|
188
188
|
if profile["name"] == profileName
|
|
189
189
|
profileId = profile['id']
|
|
@@ -197,12 +197,12 @@ module TDUploadService
|
|
|
197
197
|
return profileId
|
|
198
198
|
end
|
|
199
199
|
|
|
200
|
-
def self.get_testing_group_ids(authToken, testingGroupNames)
|
|
200
|
+
def self.get_testing_group_ids(authToken, testingGroupNames, api_endpoint = BASE_URL)
|
|
201
201
|
testingGroupIds = []
|
|
202
202
|
remainingGroupNames = Set.new(testingGroupNames)
|
|
203
203
|
|
|
204
204
|
begin
|
|
205
|
-
groups = TDUploadService.get_testing_groups(auth_token: authToken)
|
|
205
|
+
groups = TDUploadService.get_testing_groups(auth_token: authToken, api_endpoint: api_endpoint)
|
|
206
206
|
|
|
207
207
|
groups.each do |group|
|
|
208
208
|
if remainingGroupNames.include?(group["name"])
|
|
@@ -219,17 +219,18 @@ module TDUploadService
|
|
|
219
219
|
return testingGroupIds
|
|
220
220
|
end
|
|
221
221
|
|
|
222
|
-
def self.create_profile(authToken, profileName, profileAuthType, profileUsername, profilePassword, profileTestingGroupNames)
|
|
222
|
+
def self.create_profile(authToken, profileName, profileAuthType, profileUsername, profilePassword, profileTestingGroupNames, api_endpoint = BASE_URL)
|
|
223
223
|
# Get testing group IDs
|
|
224
224
|
if !profileTestingGroupNames&.empty?
|
|
225
|
-
profileTestingGroupIds = TDUploadService.get_testing_group_ids(authToken, profileTestingGroupNames)
|
|
225
|
+
profileTestingGroupIds = TDUploadService.get_testing_group_ids(authToken, profileTestingGroupNames, api_endpoint)
|
|
226
226
|
end
|
|
227
|
-
|
|
227
|
+
|
|
228
228
|
# Create
|
|
229
229
|
begin
|
|
230
230
|
new_profile = TDUploadService.create_distribution_profile(
|
|
231
231
|
name: profileName,
|
|
232
|
-
auth_token: authToken
|
|
232
|
+
auth_token: authToken,
|
|
233
|
+
api_endpoint: api_endpoint
|
|
233
234
|
)
|
|
234
235
|
if new_profile.nil?
|
|
235
236
|
raise "Error: The new profile could not be created."
|
|
@@ -248,7 +249,8 @@ module TDUploadService
|
|
|
248
249
|
username: profileUsername,
|
|
249
250
|
password: profilePassword,
|
|
250
251
|
testing_group_ids: profileTestingGroupIds,
|
|
251
|
-
auth_token: authToken
|
|
252
|
+
auth_token: authToken,
|
|
253
|
+
api_endpoint: api_endpoint
|
|
252
254
|
)
|
|
253
255
|
if configured_profile.nil?
|
|
254
256
|
raise "Error: The new profile could not be configured."
|