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.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/credentials_manager/lib/credentials_manager.rb +1 -1
  3. data/fastlane/lib/fastlane/actions/ipa.rb +2 -1
  4. data/fastlane/lib/fastlane/actions/mailgun.rb +15 -2
  5. data/fastlane/lib/fastlane/actions/scan.rb +14 -0
  6. data/fastlane/lib/fastlane/documentation/docs_generator.rb +24 -1
  7. data/fastlane/lib/fastlane/environment_printer.rb +2 -1
  8. data/fastlane/lib/fastlane/fast_file.rb +4 -4
  9. data/fastlane/lib/fastlane/version.rb +1 -1
  10. data/fastlane_core/lib/fastlane_core.rb +1 -1
  11. data/fastlane_core/lib/fastlane_core/configuration/config_item.rb +44 -2
  12. data/fastlane_core/lib/fastlane_core/device_manager.rb +15 -0
  13. data/fastlane_core/lib/fastlane_core/helper.rb +1 -1
  14. data/fastlane_core/lib/fastlane_core/ui/disable_colors.rb +4 -4
  15. data/frameit/lib/frameit/config_parser.rb +8 -13
  16. data/frameit/lib/frameit/editor.rb +3 -2
  17. data/gym/lib/gym/options.rb +4 -2
  18. data/match/README.md +2 -2
  19. data/match/lib/match.rb +5 -19
  20. data/match/lib/match/generator.rb +8 -1
  21. data/match/lib/match/git_helper.rb +3 -1
  22. data/match/lib/match/nuke.rb +18 -14
  23. data/match/lib/match/options.rb +13 -2
  24. data/match/lib/match/runner.rb +20 -8
  25. data/match/lib/match/table_printer.rb +5 -4
  26. data/match/lib/match/utils.rb +12 -8
  27. data/scan/lib/scan/options.rb +24 -1
  28. data/scan/lib/scan/runner.rb +12 -11
  29. data/scan/lib/scan/test_command_generator.rb +10 -2
  30. data/sigh/lib/sigh/download_all.rb +1 -1
  31. data/sigh/lib/sigh/runner.rb +2 -2
  32. data/snapshot/lib/snapshot/options.rb +2 -1
  33. data/snapshot/lib/snapshot/runner.rb +12 -12
  34. data/spaceship/lib/spaceship.rb +1 -0
  35. data/spaceship/lib/spaceship/base.rb +27 -4
  36. data/spaceship/lib/spaceship/client.rb +3 -2
  37. data/spaceship/lib/spaceship/du/du_client.rb +26 -16
  38. data/spaceship/lib/spaceship/portal/app.rb +1 -1
  39. data/spaceship/lib/spaceship/portal/person.rb +53 -0
  40. data/spaceship/lib/spaceship/portal/persons.rb +49 -0
  41. data/spaceship/lib/spaceship/portal/portal.rb +2 -0
  42. data/spaceship/lib/spaceship/portal/portal_client.rb +69 -10
  43. data/spaceship/lib/spaceship/portal/provisioning_profile.rb +29 -1
  44. data/spaceship/lib/spaceship/tunes/application.rb +11 -1
  45. data/spaceship/lib/spaceship/tunes/iap.rb +113 -0
  46. data/spaceship/lib/spaceship/tunes/iap_detail.rb +185 -0
  47. data/spaceship/lib/spaceship/tunes/iap_families.rb +62 -0
  48. data/spaceship/lib/spaceship/tunes/iap_family_details.rb +59 -0
  49. data/spaceship/lib/spaceship/tunes/iap_family_list.rb +33 -0
  50. data/spaceship/lib/spaceship/tunes/iap_list.rb +72 -0
  51. data/spaceship/lib/spaceship/tunes/iap_status.rb +48 -0
  52. data/spaceship/lib/spaceship/tunes/iap_type.rb +45 -0
  53. data/spaceship/lib/spaceship/tunes/tunes.rb +1 -0
  54. data/spaceship/lib/spaceship/tunes/tunes_client.rb +163 -1
  55. 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