fastlane 2.13.0 → 2.14.0
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/credentials_manager/lib/credentials_manager.rb +1 -1
- data/fastlane/lib/fastlane/actions/ipa.rb +2 -1
- data/fastlane/lib/fastlane/actions/mailgun.rb +15 -2
- data/fastlane/lib/fastlane/actions/scan.rb +14 -0
- data/fastlane/lib/fastlane/documentation/docs_generator.rb +24 -1
- data/fastlane/lib/fastlane/environment_printer.rb +2 -1
- data/fastlane/lib/fastlane/fast_file.rb +4 -4
- data/fastlane/lib/fastlane/version.rb +1 -1
- data/fastlane_core/lib/fastlane_core.rb +1 -1
- data/fastlane_core/lib/fastlane_core/configuration/config_item.rb +44 -2
- data/fastlane_core/lib/fastlane_core/device_manager.rb +15 -0
- data/fastlane_core/lib/fastlane_core/helper.rb +1 -1
- data/fastlane_core/lib/fastlane_core/ui/disable_colors.rb +4 -4
- data/frameit/lib/frameit/config_parser.rb +8 -13
- data/frameit/lib/frameit/editor.rb +3 -2
- data/gym/lib/gym/options.rb +4 -2
- data/match/README.md +2 -2
- data/match/lib/match.rb +5 -19
- data/match/lib/match/generator.rb +8 -1
- data/match/lib/match/git_helper.rb +3 -1
- data/match/lib/match/nuke.rb +18 -14
- data/match/lib/match/options.rb +13 -2
- data/match/lib/match/runner.rb +20 -8
- data/match/lib/match/table_printer.rb +5 -4
- data/match/lib/match/utils.rb +12 -8
- data/scan/lib/scan/options.rb +24 -1
- data/scan/lib/scan/runner.rb +12 -11
- data/scan/lib/scan/test_command_generator.rb +10 -2
- data/sigh/lib/sigh/download_all.rb +1 -1
- data/sigh/lib/sigh/runner.rb +2 -2
- data/snapshot/lib/snapshot/options.rb +2 -1
- data/snapshot/lib/snapshot/runner.rb +12 -12
- data/spaceship/lib/spaceship.rb +1 -0
- data/spaceship/lib/spaceship/base.rb +27 -4
- data/spaceship/lib/spaceship/client.rb +3 -2
- data/spaceship/lib/spaceship/du/du_client.rb +26 -16
- data/spaceship/lib/spaceship/portal/app.rb +1 -1
- data/spaceship/lib/spaceship/portal/person.rb +53 -0
- data/spaceship/lib/spaceship/portal/persons.rb +49 -0
- data/spaceship/lib/spaceship/portal/portal.rb +2 -0
- data/spaceship/lib/spaceship/portal/portal_client.rb +69 -10
- data/spaceship/lib/spaceship/portal/provisioning_profile.rb +29 -1
- data/spaceship/lib/spaceship/tunes/application.rb +11 -1
- data/spaceship/lib/spaceship/tunes/iap.rb +113 -0
- data/spaceship/lib/spaceship/tunes/iap_detail.rb +185 -0
- data/spaceship/lib/spaceship/tunes/iap_families.rb +62 -0
- data/spaceship/lib/spaceship/tunes/iap_family_details.rb +59 -0
- data/spaceship/lib/spaceship/tunes/iap_family_list.rb +33 -0
- data/spaceship/lib/spaceship/tunes/iap_list.rb +72 -0
- data/spaceship/lib/spaceship/tunes/iap_status.rb +48 -0
- data/spaceship/lib/spaceship/tunes/iap_type.rb +45 -0
- data/spaceship/lib/spaceship/tunes/tunes.rb +1 -0
- data/spaceship/lib/spaceship/tunes/tunes_client.rb +163 -1
- metadata +21 -5
@@ -0,0 +1,185 @@
|
|
1
|
+
module Spaceship
|
2
|
+
module Tunes
|
3
|
+
class IAPDetail < TunesBase
|
4
|
+
# @return (Spaceship::Tunes::Application) A reference to the application
|
5
|
+
attr_accessor :application
|
6
|
+
|
7
|
+
# @return (Integer) the IAP id
|
8
|
+
attr_accessor :purchase_id
|
9
|
+
|
10
|
+
# @return (Bool) if it is a news subscription
|
11
|
+
attr_accessor :is_news_subscription
|
12
|
+
|
13
|
+
# @return (String) the IAP Referencename
|
14
|
+
attr_accessor :reference_name
|
15
|
+
|
16
|
+
# @return (String) the IAP Product-Id
|
17
|
+
attr_accessor :product_id
|
18
|
+
|
19
|
+
# @return (String) free trial period
|
20
|
+
attr_accessor :subscription_free_trial
|
21
|
+
|
22
|
+
# @return (String) subscription duration
|
23
|
+
attr_accessor :subscription_duration
|
24
|
+
|
25
|
+
# @return (Bool) Cleared for sale flag
|
26
|
+
attr_accessor :cleared_for_sale
|
27
|
+
|
28
|
+
attr_accessor :review_screenshot
|
29
|
+
|
30
|
+
# @return (String) the notes for the review team
|
31
|
+
attr_accessor :review_notes
|
32
|
+
|
33
|
+
# @return (Hash) subscription pricing target
|
34
|
+
attr_accessor :subscription_price_target
|
35
|
+
|
36
|
+
attr_mapping({
|
37
|
+
'adamId' => :purchase_id,
|
38
|
+
'referenceName.value' => :reference_name,
|
39
|
+
'productId.value' => :product_id,
|
40
|
+
'isNewsSubscription' => :is_news_subscription,
|
41
|
+
'pricingDurationType.value' => :subscription_duration,
|
42
|
+
'freeTrialDurationType.value' => :subscription_free_trial,
|
43
|
+
'clearedForSale.value' => :cleared_for_sale
|
44
|
+
})
|
45
|
+
|
46
|
+
class << self
|
47
|
+
def factory(attrs)
|
48
|
+
return self.new(attrs)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# @return (Hash) Hash of languages
|
53
|
+
# @example: {
|
54
|
+
# 'de-DE': {
|
55
|
+
# name: "Name shown in AppStore",
|
56
|
+
# description: "Description of the In app Purchase"
|
57
|
+
#
|
58
|
+
# }
|
59
|
+
# }
|
60
|
+
def versions
|
61
|
+
parsed_versions = {}
|
62
|
+
raw_versions = raw_data["versions"].first["details"]["value"]
|
63
|
+
raw_versions.each do |localized_version|
|
64
|
+
language = localized_version["value"]["localeCode"]
|
65
|
+
parsed_versions[language.to_sym] = {
|
66
|
+
name: localized_version["value"]["name"]["value"],
|
67
|
+
description: localized_version["value"]["description"]["value"]
|
68
|
+
}
|
69
|
+
end
|
70
|
+
return parsed_versions
|
71
|
+
end
|
72
|
+
|
73
|
+
# @return (Array) pricing intervals
|
74
|
+
# @example:
|
75
|
+
# [
|
76
|
+
# {
|
77
|
+
# country: "WW",
|
78
|
+
# begin_date: nil,
|
79
|
+
# end_date: nil,
|
80
|
+
# tier: 1
|
81
|
+
# }
|
82
|
+
# ]
|
83
|
+
def pricing_intervals
|
84
|
+
parsed_intervals = []
|
85
|
+
raw_data["pricingIntervals"].each do |interval|
|
86
|
+
parsed_intervals << {
|
87
|
+
tier: interval["value"]["tierStem"].to_i,
|
88
|
+
begin_date: interval["value"]["priceTierEffectiveDate"],
|
89
|
+
end_date: interval["value"]["priceTierEndDate"],
|
90
|
+
grandfathered: interval["value"]["grandfathered"],
|
91
|
+
country: interval["value"]["country"]
|
92
|
+
}
|
93
|
+
end
|
94
|
+
return parsed_intervals
|
95
|
+
end
|
96
|
+
|
97
|
+
# @return (String) Human Readable type of the purchase
|
98
|
+
def type
|
99
|
+
Tunes::IAPType.get_from_string(raw_data["addOnType"])
|
100
|
+
end
|
101
|
+
|
102
|
+
# @return (String) Human Readable status of the purchase
|
103
|
+
def status
|
104
|
+
Tunes::IAPStatus.get_from_string(raw_data["versions"].first["status"])
|
105
|
+
end
|
106
|
+
|
107
|
+
# Saves the current In-App-Purchase
|
108
|
+
def save!
|
109
|
+
# Transform localization versions back to original format.
|
110
|
+
versions_array = []
|
111
|
+
versions.each do |language, value|
|
112
|
+
versions_array << {
|
113
|
+
value: {
|
114
|
+
description: { value: value[:description] },
|
115
|
+
name: { value: value[:name] },
|
116
|
+
localeCode: language.to_s
|
117
|
+
}
|
118
|
+
}
|
119
|
+
end
|
120
|
+
|
121
|
+
raw_data.set(["versions"], [{ reviewNotes: @review_notes, details: { value: versions_array } }])
|
122
|
+
|
123
|
+
# transform pricingDetails
|
124
|
+
intervals_array = []
|
125
|
+
pricing_intervals.each do |interval|
|
126
|
+
intervals_array << {
|
127
|
+
value: {
|
128
|
+
tierStem: interval[:tier],
|
129
|
+
priceTierEffectiveDate: interval[:begin_date],
|
130
|
+
priceTierEndDate: interval[:end_date],
|
131
|
+
country: interval[:country] || "WW",
|
132
|
+
grandfathered: interval[:grandfathered]
|
133
|
+
}
|
134
|
+
}
|
135
|
+
end
|
136
|
+
|
137
|
+
if subscription_price_target
|
138
|
+
intervals_array = []
|
139
|
+
pricing_calculator = client.iap_subscription_pricing_target(app_id: application.apple_id, purchase_id: purchase_id, currency: subscription_price_target[:currency], tier: subscription_price_target[:tier])
|
140
|
+
pricing_calculator.each do |language_code, value|
|
141
|
+
intervals_array << {
|
142
|
+
value: {
|
143
|
+
tierStem: value["tierStem"],
|
144
|
+
priceTierEffectiveDate: value["priceTierEffectiveDate"],
|
145
|
+
priceTierEndDate: value["priceTierEndDate"],
|
146
|
+
country: language_code,
|
147
|
+
grandfathered: { value: "FUTURE_NONE" }
|
148
|
+
}
|
149
|
+
}
|
150
|
+
end
|
151
|
+
|
152
|
+
end
|
153
|
+
|
154
|
+
raw_data.set(["pricingIntervals"], intervals_array)
|
155
|
+
|
156
|
+
if @review_screenshot
|
157
|
+
# Upload Screenshot
|
158
|
+
upload_file = UploadFile.from_path @review_screenshot
|
159
|
+
screenshot_data = client.upload_purchase_review_screenshot(application.apple_id, upload_file)
|
160
|
+
new_screenshot = {
|
161
|
+
"value" => {
|
162
|
+
"assetToken" => screenshot_data["token"],
|
163
|
+
"sortOrder" => 0,
|
164
|
+
"type" => "SortedScreenShot",
|
165
|
+
"originalFileName" => upload_file.file_name,
|
166
|
+
"size" => screenshot_data["length"],
|
167
|
+
"height" => screenshot_data["height"],
|
168
|
+
"width" => screenshot_data["width"],
|
169
|
+
"checksum" => screenshot_data["md5"]
|
170
|
+
}
|
171
|
+
}
|
172
|
+
|
173
|
+
raw_data["versions"][0]["reviewScreenshot"] = new_screenshot
|
174
|
+
end
|
175
|
+
# Update the Purchase
|
176
|
+
client.update_iap!(app_id: application.apple_id, purchase_id: self.purchase_id, data: raw_data)
|
177
|
+
end
|
178
|
+
|
179
|
+
# Deletes In-App-Purchase
|
180
|
+
def delete!
|
181
|
+
client.delete_iap!(app_id: application.apple_id, purchase_id: self.purchase_id)
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
|
2
|
+
module Spaceship
|
3
|
+
module Tunes
|
4
|
+
class IAPFamilies < TunesBase
|
5
|
+
# @return (Spaceship::Tunes::Application) A reference to the application
|
6
|
+
attr_accessor :application
|
7
|
+
|
8
|
+
class << self
|
9
|
+
def factory(attrs)
|
10
|
+
return self.new(attrs)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# Create a new Purchase Family
|
15
|
+
# a freshly created family has to have atleast one product.
|
16
|
+
# the product will be created, and versions/pricing_intervals and so on
|
17
|
+
# should be set by subsequent edit.
|
18
|
+
# @param name (String) Familyname
|
19
|
+
# @param product_id (String) New Product's id
|
20
|
+
# @param reference_name (String) Reference name of the new product
|
21
|
+
# @param versions (Hash) Localized Familie names
|
22
|
+
# @example
|
23
|
+
# versions: {
|
24
|
+
# 'de-DE': {
|
25
|
+
# subscription_name: "Subname German",
|
26
|
+
# name: 'App Name German',
|
27
|
+
# },
|
28
|
+
# 'da': {
|
29
|
+
# subscription_name: "Subname DA",
|
30
|
+
# name: 'App Name DA',
|
31
|
+
# }
|
32
|
+
# }
|
33
|
+
|
34
|
+
def create!(name: nil, product_id: nil, reference_name: nil, versions: {})
|
35
|
+
versions_array = []
|
36
|
+
versions.each do |language_code, value|
|
37
|
+
versions_array << {
|
38
|
+
value: {
|
39
|
+
subscriptionName: { value: value[:subscription_name] },
|
40
|
+
name: { value: value[:name] },
|
41
|
+
localeCode: { value: language_code.to_s }
|
42
|
+
}
|
43
|
+
}
|
44
|
+
end
|
45
|
+
client.create_iap_family(app_id: self.application.apple_id, name: name, product_id: product_id, reference_name: reference_name, versions: versions_array)
|
46
|
+
end
|
47
|
+
|
48
|
+
# returns a list of all families
|
49
|
+
def all
|
50
|
+
r = client.iap_families(app_id: self.application.apple_id)
|
51
|
+
return_families = []
|
52
|
+
r.each do |family|
|
53
|
+
attrs = family
|
54
|
+
attrs[:application] = self.application
|
55
|
+
loaded_family = Tunes::IAPFamilyList.factory(attrs)
|
56
|
+
return_families << loaded_family
|
57
|
+
end
|
58
|
+
return_families
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
|
2
|
+
module Spaceship
|
3
|
+
module Tunes
|
4
|
+
class IAPFamilyDetails < TunesBase
|
5
|
+
# @return (Spaceship::Tunes::Application) A reference to the application
|
6
|
+
attr_accessor :application
|
7
|
+
|
8
|
+
# @return (String) the family name
|
9
|
+
attr_accessor :name
|
10
|
+
|
11
|
+
# @return (Intger) the Family Id
|
12
|
+
attr_accessor :family_id
|
13
|
+
|
14
|
+
attr_mapping({
|
15
|
+
'id' => :family_id,
|
16
|
+
'name.value' => :name
|
17
|
+
})
|
18
|
+
|
19
|
+
class << self
|
20
|
+
def factory(attrs)
|
21
|
+
return self.new(attrs)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# @return (Hash) localized names
|
26
|
+
def versions
|
27
|
+
parsed_versions = {}
|
28
|
+
raw_versions = raw_data["details"]["value"]
|
29
|
+
raw_versions.each do |version|
|
30
|
+
language = version["value"]["localeCode"]["value"]
|
31
|
+
parsed_versions[language.to_sym] = {
|
32
|
+
subscription_name: version["value"]["subscriptionName"]["value"],
|
33
|
+
name: version["value"]["name"]["value"]
|
34
|
+
}
|
35
|
+
end
|
36
|
+
return parsed_versions
|
37
|
+
end
|
38
|
+
|
39
|
+
# modify existing family
|
40
|
+
def save!
|
41
|
+
# Transform localization versions back to original format.
|
42
|
+
versions_array = []
|
43
|
+
versions.each do |language_code, value|
|
44
|
+
versions_array << {
|
45
|
+
value: {
|
46
|
+
subscriptionName: { value: value[:subscription_name] },
|
47
|
+
name: { value: value[:name] },
|
48
|
+
localeCode: { value: language_code.to_s }
|
49
|
+
}
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
53
|
+
raw_data.set(["details"], { value: versions_array })
|
54
|
+
|
55
|
+
client.update_iap_family!(app_id: application.apple_id, family_id: self.family_id, data: raw_data)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
|
2
|
+
module Spaceship
|
3
|
+
module Tunes
|
4
|
+
class IAPFamilyList < TunesBase
|
5
|
+
# @return (Spaceship::Tunes::Application) A reference to the application
|
6
|
+
attr_accessor :application
|
7
|
+
|
8
|
+
# @return (String) the family name
|
9
|
+
attr_accessor :name
|
10
|
+
|
11
|
+
# @return (Intger) the Family Id
|
12
|
+
attr_accessor :family_id
|
13
|
+
|
14
|
+
attr_mapping({
|
15
|
+
'id' => :family_id,
|
16
|
+
'name.value' => :name
|
17
|
+
})
|
18
|
+
|
19
|
+
class << self
|
20
|
+
def factory(attrs)
|
21
|
+
return self.new(attrs)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# return a editable family object
|
26
|
+
def edit
|
27
|
+
attrs = client.load_iap_family(app_id: application.apple_id, family_id: self.family_id)
|
28
|
+
attrs[:application] = application
|
29
|
+
Tunes::IAPFamilyDetails.factory(attrs)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
|
2
|
+
module Spaceship
|
3
|
+
module Tunes
|
4
|
+
class IAPList < TunesBase
|
5
|
+
# @return (Spaceship::Tunes::Application) A reference to the application
|
6
|
+
attr_accessor :application
|
7
|
+
|
8
|
+
# @return (String) the IAP Referencename
|
9
|
+
attr_accessor :reference_name
|
10
|
+
|
11
|
+
# @return (String) the IAP Product-Id
|
12
|
+
attr_accessor :product_id
|
13
|
+
|
14
|
+
# @return (String) Family Reference Name
|
15
|
+
attr_accessor :family_reference_name
|
16
|
+
|
17
|
+
attr_accessor :duration_days
|
18
|
+
attr_accessor :versions
|
19
|
+
attr_accessor :purple_apple_id
|
20
|
+
attr_accessor :last_modfied_date
|
21
|
+
attr_accessor :is_news_subscription
|
22
|
+
attr_accessor :number_of_codes
|
23
|
+
attr_accessor :maximum_number_of_codes
|
24
|
+
attr_accessor :app_maximum_number_of_codes
|
25
|
+
attr_accessor :is_editable
|
26
|
+
attr_accessor :is_required
|
27
|
+
attr_accessor :can_delete_addon
|
28
|
+
|
29
|
+
attr_mapping({
|
30
|
+
'adamId' => :purchase_id,
|
31
|
+
'referenceName' => :reference_name,
|
32
|
+
'familyReferenceName' => :family_reference_name,
|
33
|
+
'vendorId' => :product_id,
|
34
|
+
'durationDays' => :duration_days,
|
35
|
+
'versions' => :versions,
|
36
|
+
'purpleSoftwareAdamIds' => :purple_apple_id,
|
37
|
+
'lastModifiedDate' => :last_modfied_date,
|
38
|
+
'isNewsSubscription' => :is_news_subscription,
|
39
|
+
'numberOfCodes' => :number_of_codes,
|
40
|
+
'maximumNumberOfCodes' => :maximum_number_of_codes,
|
41
|
+
'appMaximumNumberOfCodes' => :app_maximum_number_of_codes,
|
42
|
+
'isEditable' => :is_editable,
|
43
|
+
'isRequired' => :is_required,
|
44
|
+
'canDeleteAddOn' => :can_delete_addon
|
45
|
+
})
|
46
|
+
|
47
|
+
class << self
|
48
|
+
def factory(attrs)
|
49
|
+
return self.new(attrs)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def type
|
54
|
+
Tunes::IAPType.get_from_string(raw_data["addOnType"])
|
55
|
+
end
|
56
|
+
|
57
|
+
def status
|
58
|
+
Tunes::IAPStatus.get_from_string(raw_data["iTunesConnectStatus"])
|
59
|
+
end
|
60
|
+
|
61
|
+
def edit
|
62
|
+
attrs = client.load_iap(app_id: application.apple_id, purchase_id: self.purchase_id)
|
63
|
+
attrs[:application] = application
|
64
|
+
Tunes::IAPDetail.factory(attrs)
|
65
|
+
end
|
66
|
+
|
67
|
+
def delete!
|
68
|
+
client.delete_iap!(app_id: application.apple_id, purchase_id: self.purchase_id)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Spaceship
|
2
|
+
module Tunes
|
3
|
+
# Defines the different states of an in-app purchase
|
4
|
+
#
|
5
|
+
# As specified by Apple: https://developer.apple.com/library/content/documentation/LanguagesUtilities/Conceptual/iTunesConnectInAppPurchase_Guide/Chapters/WorkingWithYourProductsStatus.html
|
6
|
+
module IAPStatus
|
7
|
+
# IAP created, but missing screenshot/metadata
|
8
|
+
MISSING_METADATA = "Missing Metadata"
|
9
|
+
|
10
|
+
# You can edit the metadata, change screenshot and more. Need to submit.
|
11
|
+
READY_TO_SUBMIT = "Ready to Submit"
|
12
|
+
|
13
|
+
# Waiting for Apple's Review
|
14
|
+
WAITING_FOR_REVIEW = "Waiting For Review"
|
15
|
+
|
16
|
+
# Currently in Review
|
17
|
+
IN_REVIEW = "In Review"
|
18
|
+
|
19
|
+
# Approved (and currently available)
|
20
|
+
APPROVED = "Approved"
|
21
|
+
|
22
|
+
# Developer deleted
|
23
|
+
DELETED = "Deleted"
|
24
|
+
|
25
|
+
# In-app purchase rejected for whatever reason
|
26
|
+
REJECTED = "Rejected"
|
27
|
+
|
28
|
+
# Get the iap status matching based on a string (given by iTunes Connect)
|
29
|
+
def self.get_from_string(text)
|
30
|
+
mapping = {
|
31
|
+
'missingMetadata' => MISSING_METADATA,
|
32
|
+
'readyToSubmit' => READY_TO_SUBMIT,
|
33
|
+
'waitingForReview' => WAITING_FOR_REVIEW,
|
34
|
+
'inReview' => IN_REVIEW,
|
35
|
+
'readyForSale' => APPROVED,
|
36
|
+
'deleted' => DELETED,
|
37
|
+
'rejected' => REJECTED
|
38
|
+
}
|
39
|
+
|
40
|
+
mapping.each do |itc_status, readable_status|
|
41
|
+
return readable_status if itc_status == text
|
42
|
+
end
|
43
|
+
|
44
|
+
return nil
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|