fastlane 2.13.0 → 2.14.0

Sign up to get free protection for your applications and to get access to all the features.
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