spaceship/lib/spaceship/tunes/tunes_client.rb in fastlane-2.11.0 vs spaceship/lib/spaceship/tunes/tunes_client.rb in fastlane-2.12.0
- old
+ new
@@ -44,13 +44,11 @@
"https://itunesconnect.apple.com/WebObjects/iTunesConnect.woa/"
end
# @return (Array) A list of all available teams
def teams
- return @teams if @teams
- r = request(:get, "ra/user/detail")
- @teams = parse_response(r, 'data')['associatedAccounts'].sort_by do |team|
+ user_details_data['associatedAccounts'].sort_by do |team|
[
team['contentProvider']['name'],
team['contentProvider']['contentProviderId']
]
end
@@ -212,14 +210,17 @@
# e.g. {"warn"=>nil, "error"=>["operation_failed"], "info"=>nil}
different_error = raw.fetch('messages', {}).fetch('error', nil)
errors << different_error if different_error
if errors.count > 0 # they are separated by `.` by default
+ # Sample `error` content: [["Forbidden"]]
if errors.count == 1 and errors.first == "You haven't made any changes."
# This is a special error which we really don't care about
elsif errors.count == 1 and errors.first.include?("try again later")
raise ITunesConnectTemporaryError.new, errors.first
+ elsif errors.count == 1 and errors.first.include?("Forbidden")
+ raise_insuffient_permission_error!
else
raise ITunesConnectError.new, errors.join(' ')
end
end
@@ -594,18 +595,65 @@
r = request(:get, '/WebObjects/iTunesConnect.woa/ra/apps/version/ref')
data = parse_response(r, 'data')
Spaceship::Tunes::AppVersionRef.factory(data)
end
+ # Fetch the general information of the user, is used by various methods across spaceship
+ # Sample return value
+ # => {"associatedAccounts"=>
+ # [{"contentProvider"=>{"contentProviderId"=>11142800, "name"=>"Felix Krause", "contentProviderTypes"=>["Purple Software"]}, "roles"=>["Developer"], "lastLogin"=>1468784113000}],
+ # "sessionToken"=>{"dsId"=>"8501011116", "contentProviderId"=>18111111, "expirationDate"=>nil, "ipAddress"=>nil},
+ # "permittedActivities"=>
+ # {"EDIT"=>
+ # ["UserManagementSelf",
+ # "GameCenterTestData",
+ # "AppAddonCreation"],
+ # "REPORT"=>
+ # ["UserManagementSelf",
+ # "AppAddonCreation"],
+ # "VIEW"=>
+ # ["TestFlightAppExternalTesterManagement",
+ # ...
+ # "HelpGeneral",
+ # "HelpApplicationLoader"]},
+ # "preferredCurrencyCode"=>"EUR",
+ # "preferredCountryCode"=>nil,
+ # "countryOfOrigin"=>"AT",
+ # "isLocaleNameReversed"=>false,
+ # "feldsparToken"=>nil,
+ # "feldsparChannelName"=>nil,
+ # "hasPendingFeldsparBindingRequest"=>false,
+ # "isLegalUser"=>false,
+ # "userId"=>"1771111155",
+ # "firstname"=>"Detlef",
+ # "lastname"=>"Mueller",
+ # "isEmailInvalid"=>false,
+ # "hasContractInfo"=>false,
+ # "canEditITCUsersAndRoles"=>false,
+ # "canViewITCUsersAndRoles"=>true,
+ # "canEditIAPUsersAndRoles"=>false,
+ # "transporterEnabled"=>false,
+ # "contentProviderFeatures"=>["APP_SILOING", "PROMO_CODE_REDESIGN", ...],
+ # "contentProviderType"=>"Purple Software",
+ # "displayName"=>"Detlef",
+ # "contentProviderId"=>"18742800",
+ # "userFeatures"=>[],
+ # "visibility"=>true,
+ # "DYCVisibility"=>false,
+ # "contentProvider"=>"Felix Krause",
+ # "userName"=>"detlef@krausefx.com"}
+ def user_details_data
+ return @_cached_user_details if @_cached_user_details
+ r = request(:get, '/WebObjects/iTunesConnect.woa/ra/user/detail')
+ @_cached_user_details = parse_response(r, 'data')
+ end
+
# Fetches the User Detail information from ITC. This gets called often and almost never changes
# so we cache it
# @return [UserDetail] the response
def user_detail_data
- return @cached if @cached
- r = request(:get, '/WebObjects/iTunesConnect.woa/ra/user/detail')
- data = parse_response(r, 'data')
- @cached = Spaceship::Tunes::UserDetail.factory(data)
+ @_cached_user_detail_data ||= Spaceship::Tunes::UserDetail.factory(user_details_data)
end
#####################################################
# @!group CandiateBuilds
#####################################################
@@ -629,11 +677,17 @@
return parse_response(r, 'data')
rescue Spaceship::Client::UnexpectedResponse => ex
# Build trains fail randomly very often
# we need to catch those errors and retry
# https://github.com/fastlane/fastlane/issues/6419
- if ex.to_s.include?("ITC.response.error.OPERATION_FAILED")
+ retry_error_messages = [
+ "ITC.response.error.OPERATION_FAILED",
+ "Internal Server Error",
+ "Service Unavailable"
+ ].freeze
+
+ if retry_error_messages.any? { |message| ex.to_s.include?(message) }
tries -= 1
if tries > 0
logger.warn("Received temporary server error from iTunes Connect. Retrying the request...")
sleep 3 unless defined? SpecHelper
retry
@@ -868,10 +922,14 @@
url = tester.url(app_id)[:index_by_app]
r = request(:get, url)
parse_response(r, 'data')['users']
end
+ # Returns a list of available testing groups
+ # e.g.
+ # {"b6f65dbd-c845-4d91-bc39-0b661d608970" => "Boarding",
+ # "70402368-9deb-409f-9a26-bb3f215dfee3" => "Automatic"}
def groups
return @cached_groups if @cached_groups
r = request(:get, '/WebObjects/iTunesConnect.woa/ra/users/pre/ext')
@cached_groups = parse_response(r, 'data')['groups']
end
@@ -879,24 +937,45 @@
def create_tester!(tester: nil, email: nil, first_name: nil, last_name: nil, groups: nil)
url = tester.url[:create]
raise "Action not provided for this tester type." unless url
tester_data = {
- emailAddress: {
- value: email
- },
- firstName: {
- value: first_name || ""
- },
- lastName: {
- value: last_name || ""
- },
- testing: {
- value: true
+ emailAddress: {
+ value: email
+ },
+ firstName: {
+ value: first_name || ""
+ },
+ lastName: {
+ value: last_name || ""
+ },
+ testing: {
+ value: true
+ }
+ }
+
+ if groups
+ tester_data[:groups] = groups.map do |group_name_or_group_id|
+ if self.groups.value?(group_name_or_group_id)
+ # This is an existing group, let's use that, the user specified the group name
+ group_name = group_name_or_group_id
+ group_id = self.groups.key(group_name_or_group_id)
+ elsif self.groups.key?(group_name_or_group_id)
+ # This is an existing group, let's use that, the user specified the group ID
+ group_name = self.groups[group_name_or_group_id]
+ group_id = group_name_or_group_id
+ else
+ group_name = group_name_or_group_id
+ group_id = nil # this is expected by the iTC API
+ end
+
+ {
+ "id" => group_id,
+ "name" => {
+ "value" => group_name
}
}
- if groups
- tester_data[:groups] = groups.map { |x| { "id" => x } }
+ end
end
data = { testers: [tester_data] }
r = request(:post) do |req|