fastlane 2.156.1 → 2.157.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 (60) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +80 -80
  3. data/deliver/lib/deliver.rb +1 -0
  4. data/deliver/lib/deliver/app_screenshot_iterator.rb +26 -29
  5. data/deliver/lib/deliver/detect_values.rb +4 -1
  6. data/deliver/lib/deliver/languages.rb +7 -0
  7. data/deliver/lib/deliver/loader.rb +4 -5
  8. data/deliver/lib/deliver/runner.rb +7 -5
  9. data/deliver/lib/deliver/upload_screenshots.rb +34 -17
  10. data/fastlane/lib/fastlane/actions/app_store_connect_api_key.rb +120 -0
  11. data/fastlane/lib/fastlane/actions/commit_version_bump.rb +1 -1
  12. data/fastlane/lib/fastlane/actions/docs/upload_to_play_store.md +2 -0
  13. data/fastlane/lib/fastlane/actions/docs/upload_to_testflight.md +17 -1
  14. data/fastlane/lib/fastlane/actions/set_changelog.rb +2 -2
  15. data/fastlane/lib/fastlane/actions/sonar.rb +5 -0
  16. data/fastlane/lib/fastlane/actions/spaceship_stats.rb +73 -0
  17. data/fastlane/lib/fastlane/actions/upload_to_testflight.rb +4 -0
  18. data/fastlane/lib/fastlane/version.rb +1 -1
  19. data/fastlane/swift/Deliverfile.swift +1 -1
  20. data/fastlane/swift/DeliverfileProtocol.swift +1 -1
  21. data/fastlane/swift/Fastlane.swift +68 -8
  22. data/fastlane/swift/Gymfile.swift +1 -1
  23. data/fastlane/swift/GymfileProtocol.swift +1 -1
  24. data/fastlane/swift/Matchfile.swift +1 -1
  25. data/fastlane/swift/MatchfileProtocol.swift +1 -1
  26. data/fastlane/swift/Precheckfile.swift +1 -1
  27. data/fastlane/swift/PrecheckfileProtocol.swift +1 -1
  28. data/fastlane/swift/Scanfile.swift +1 -1
  29. data/fastlane/swift/ScanfileProtocol.swift +1 -1
  30. data/fastlane/swift/Screengrabfile.swift +1 -1
  31. data/fastlane/swift/ScreengrabfileProtocol.swift +1 -1
  32. data/fastlane/swift/Snapshotfile.swift +1 -1
  33. data/fastlane/swift/SnapshotfileProtocol.swift +1 -1
  34. data/fastlane_core/lib/fastlane_core/itunes_transporter.rb +71 -42
  35. data/gym/lib/gym/error_handler.rb +1 -1
  36. data/pilot/lib/pilot/build_manager.rb +18 -4
  37. data/pilot/lib/pilot/manager.rb +15 -5
  38. data/pilot/lib/pilot/options.rb +16 -0
  39. data/produce/lib/produce/itunes_connect.rb +2 -2
  40. data/screengrab/lib/screengrab/runner.rb +1 -0
  41. data/sigh/lib/sigh/runner.rb +4 -4
  42. data/spaceship/lib/spaceship.rb +4 -0
  43. data/spaceship/lib/spaceship/client.rb +2 -0
  44. data/spaceship/lib/spaceship/connect_api.rb +0 -15
  45. data/spaceship/lib/spaceship/connect_api/api_client.rb +270 -0
  46. data/spaceship/lib/spaceship/connect_api/client.rb +139 -213
  47. data/spaceship/lib/spaceship/connect_api/provisioning/client.rb +8 -17
  48. data/spaceship/lib/spaceship/connect_api/provisioning/provisioning.rb +75 -64
  49. data/spaceship/lib/spaceship/connect_api/spaceship.rb +94 -0
  50. data/spaceship/lib/spaceship/connect_api/testflight/client.rb +8 -17
  51. data/spaceship/lib/spaceship/connect_api/testflight/testflight.rb +288 -277
  52. data/spaceship/lib/spaceship/connect_api/token.rb +46 -5
  53. data/spaceship/lib/spaceship/connect_api/token_refresh_middleware.rb +24 -0
  54. data/spaceship/lib/spaceship/connect_api/tunes/client.rb +8 -17
  55. data/spaceship/lib/spaceship/connect_api/tunes/tunes.rb +717 -706
  56. data/spaceship/lib/spaceship/connect_api/users/client.rb +8 -17
  57. data/spaceship/lib/spaceship/connect_api/users/users.rb +28 -17
  58. data/spaceship/lib/spaceship/stats_middleware.rb +65 -0
  59. metadata +25 -19
  60. data/spaceship/lib/spaceship/connect_api/.client.rb.swp +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8ddb9f8d09ffcb09f5ddd4d6365f67d41c538e8804630e40911e058a8174aaf2
4
- data.tar.gz: 8bf0f6513c658bb9891058e5bee6fb22689bc496376e4aff6a2d2e5f1a2b9b74
3
+ metadata.gz: 54d4961677c76fce8c6ecb5e8c89f9b28ea818abd3dc886217d8eaf4e198902b
4
+ data.tar.gz: a36d89c144e59c29e7dc94eeb8f51a72b3a50a9ed2813ca700d8ee7008d778de
5
5
  SHA512:
6
- metadata.gz: 9627a6de633cc011c1cd083468869543125e4eb021f025152c3aaf0e4e6067c80bcc514e71c1d425485138df0ff7ab43fa70771d846e0270c49ad50b60dc47c1
7
- data.tar.gz: 177ba0af8b688d96e5374f7a3175663cebe4e3bae3966733880e75e0634cc4e1cdedc3f12c1c8ac0cd415b024eb3aa9385489d67f98b2e9d4e5175631d2874bf
6
+ metadata.gz: ef36ec87ab67fa77d75cb6836e994463de4f550e6ff0bc832690c734c09a8a21cd9644c90657d29894baf2b4b7e4d87269f7c8d350ce0300ee2b162f3a861870
7
+ data.tar.gz: d8a4392c60f47e7b7d73a374020c854694f27a91a59a23d33a6f0de2464efdd2b653bfb6a999faa3b1657a7aa4d29a097ef7d8cff34eeec5481bafb2e5612339
data/README.md CHANGED
@@ -34,119 +34,113 @@ If the above doesn't help, please [submit an issue](https://github.com/fastlane/
34
34
  <!-- This table is regenerated and resorted on each release -->
35
35
  <table id='team'>
36
36
  <tr>
37
- <td id='jorge-revuelta-h'>
38
- <a href='https://github.com/minuscorp'>
39
- <img src='https://github.com/minuscorp.png?size=140'>
40
- </a>
41
- <h4 align='center'><a href='https://twitter.com/minuscorp'>Jorge Revuelta H</a></h4>
42
- </td>
43
- <td id='luka-mirosevic'>
44
- <a href='https://github.com/lmirosevic'>
45
- <img src='https://github.com/lmirosevic.png?size=140'>
46
- </a>
47
- <h4 align='center'><a href='https://twitter.com/lmirosevic'>Luka Mirosevic</a></h4>
48
- </td>
49
- <td id='josh-holtz'>
50
- <a href='https://github.com/joshdholtz'>
51
- <img src='https://github.com/joshdholtz.png?size=140'>
37
+ <td id='olivier-halligon'>
38
+ <a href='https://github.com/AliSoftware'>
39
+ <img src='https://github.com/AliSoftware.png?size=140'>
52
40
  </a>
53
- <h4 align='center'><a href='https://twitter.com/joshdholtz'>Josh Holtz</a></h4>
41
+ <h4 align='center'><a href='https://twitter.com/aligatr'>Olivier Halligon</a></h4>
54
42
  </td>
55
- <td id='felix-krause'>
56
- <a href='https://github.com/KrauseFx'>
57
- <img src='https://github.com/KrauseFx.png?size=140'>
43
+ <td id='stefan-natchev'>
44
+ <a href='https://github.com/snatchev'>
45
+ <img src='https://github.com/snatchev.png?size=140'>
58
46
  </a>
59
- <h4 align='center'><a href='https://twitter.com/KrauseFx'>Felix Krause</a></h4>
47
+ <h4 align='center'><a href='https://twitter.com/snatchev'>Stefan Natchev</a></h4>
60
48
  </td>
61
- <td id='fumiya-nakamura'>
62
- <a href='https://github.com/nafu'>
63
- <img src='https://github.com/nafu.png?size=140'>
49
+ <td id='jan-piotrowski'>
50
+ <a href='https://github.com/janpio'>
51
+ <img src='https://github.com/janpio.png?size=140'>
64
52
  </a>
65
- <h4 align='center'><a href='https://twitter.com/nafu003'>Fumiya Nakamura</a></h4>
53
+ <h4 align='center'><a href='https://twitter.com/Sujan'>Jan Piotrowski</a></h4>
66
54
  </td>
67
- </tr>
68
- <tr>
69
55
  <td id='max-ott'>
70
56
  <a href='https://github.com/max-ott'>
71
57
  <img src='https://github.com/max-ott.png?size=140'>
72
58
  </a>
73
59
  <h4 align='center'><a href='https://twitter.com/ott_max'>Max Ott</a></h4>
74
60
  </td>
75
- <td id='stefan-natchev'>
76
- <a href='https://github.com/snatchev'>
77
- <img src='https://github.com/snatchev.png?size=140'>
78
- </a>
79
- <h4 align='center'><a href='https://twitter.com/snatchev'>Stefan Natchev</a></h4>
80
- </td>
81
- <td id='jérôme-lacoste'>
82
- <a href='https://github.com/lacostej'>
83
- <img src='https://github.com/lacostej.png?size=140'>
61
+ <td id='jorge-revuelta-h'>
62
+ <a href='https://github.com/minuscorp'>
63
+ <img src='https://github.com/minuscorp.png?size=140'>
84
64
  </a>
85
- <h4 align='center'><a href='https://twitter.com/lacostej'>Jérôme Lacoste</a></h4>
65
+ <h4 align='center'><a href='https://twitter.com/minuscorp'>Jorge Revuelta H</a></h4>
86
66
  </td>
67
+ </tr>
68
+ <tr>
87
69
  <td id='joshua-liebowitz'>
88
70
  <a href='https://github.com/taquitos'>
89
71
  <img src='https://github.com/taquitos.png?size=140'>
90
72
  </a>
91
73
  <h4 align='center'><a href='https://twitter.com/taquitos'>Joshua Liebowitz</a></h4>
92
74
  </td>
93
- <td id='iulian-onofrei'>
94
- <a href='https://github.com/revolter'>
95
- <img src='https://github.com/revolter.png?size=140'>
75
+ <td id='manu-wallner'>
76
+ <a href='https://github.com/milch'>
77
+ <img src='https://github.com/milch.png?size=140'>
96
78
  </a>
97
- <h4 align='center'><a href='https://twitter.com/Revolt666'>Iulian Onofrei</a></h4>
79
+ <h4 align='center'><a href='https://twitter.com/acrooow'>Manu Wallner</a></h4>
80
+ </td>
81
+ <td id='daniel-jankowski'>
82
+ <a href='https://github.com/mollyIV'>
83
+ <img src='https://github.com/mollyIV.png?size=140'>
84
+ </a>
85
+ <h4 align='center'><a href='https://twitter.com/mollyIV'>Daniel Jankowski</a></h4>
98
86
  </td>
99
- </tr>
100
- <tr>
101
87
  <td id='jimmy-dee'>
102
88
  <a href='https://github.com/jdee'>
103
89
  <img src='https://github.com/jdee.png?size=140'>
104
90
  </a>
105
91
  <h4 align='center'>Jimmy Dee</h4>
106
92
  </td>
107
- <td id='andrew-mcburney'>
108
- <a href='https://github.com/armcburney'>
109
- <img src='https://github.com/armcburney.png?size=140'>
93
+ <td id='maksym-grebenets'>
94
+ <a href='https://github.com/mgrebenets'>
95
+ <img src='https://github.com/mgrebenets.png?size=140'>
110
96
  </a>
111
- <h4 align='center'><a href='https://twitter.com/armcburney'>Andrew McBurney</a></h4>
97
+ <h4 align='center'><a href='https://twitter.com/mgrebenets'>Maksym Grebenets</a></h4>
112
98
  </td>
99
+ </tr>
100
+ <tr>
113
101
  <td id='kohki-miki'>
114
102
  <a href='https://github.com/giginet'>
115
103
  <img src='https://github.com/giginet.png?size=140'>
116
104
  </a>
117
105
  <h4 align='center'><a href='https://twitter.com/giginet'>Kohki Miki</a></h4>
118
106
  </td>
119
- <td id='jan-piotrowski'>
120
- <a href='https://github.com/janpio'>
121
- <img src='https://github.com/janpio.png?size=140'>
107
+ <td id='andrew-mcburney'>
108
+ <a href='https://github.com/armcburney'>
109
+ <img src='https://github.com/armcburney.png?size=140'>
122
110
  </a>
123
- <h4 align='center'><a href='https://twitter.com/Sujan'>Jan Piotrowski</a></h4>
111
+ <h4 align='center'><a href='https://twitter.com/armcburney'>Andrew McBurney</a></h4>
124
112
  </td>
125
- <td id='olivier-halligon'>
126
- <a href='https://github.com/AliSoftware'>
127
- <img src='https://github.com/AliSoftware.png?size=140'>
113
+ <td id='luka-mirosevic'>
114
+ <a href='https://github.com/lmirosevic'>
115
+ <img src='https://github.com/lmirosevic.png?size=140'>
128
116
  </a>
129
- <h4 align='center'><a href='https://twitter.com/aligatr'>Olivier Halligon</a></h4>
117
+ <h4 align='center'><a href='https://twitter.com/lmirosevic'>Luka Mirosevic</a></h4>
130
118
  </td>
131
- </tr>
132
- <tr>
133
- <td id='helmut-januschka'>
134
- <a href='https://github.com/hjanuschka'>
135
- <img src='https://github.com/hjanuschka.png?size=140'>
119
+ <td id='josh-holtz'>
120
+ <a href='https://github.com/joshdholtz'>
121
+ <img src='https://github.com/joshdholtz.png?size=140'>
136
122
  </a>
137
- <h4 align='center'><a href='https://twitter.com/hjanuschka'>Helmut Januschka</a></h4>
123
+ <h4 align='center'><a href='https://twitter.com/joshdholtz'>Josh Holtz</a></h4>
138
124
  </td>
139
- <td id='daniel-jankowski'>
140
- <a href='https://github.com/mollyIV'>
141
- <img src='https://github.com/mollyIV.png?size=140'>
125
+ <td id='fumiya-nakamura'>
126
+ <a href='https://github.com/nafu'>
127
+ <img src='https://github.com/nafu.png?size=140'>
142
128
  </a>
143
- <h4 align='center'><a href='https://twitter.com/mollyIV'>Daniel Jankowski</a></h4>
129
+ <h4 align='center'><a href='https://twitter.com/nafu003'>Fumiya Nakamura</a></h4>
144
130
  </td>
145
- <td id='manu-wallner'>
146
- <a href='https://github.com/milch'>
147
- <img src='https://github.com/milch.png?size=140'>
131
+ </tr>
132
+ <tr>
133
+ <td id='danielle-tomlinson'>
134
+ <a href='https://github.com/endocrimes'>
135
+ <img src='https://github.com/endocrimes.png?size=140'>
148
136
  </a>
149
- <h4 align='center'><a href='https://twitter.com/acrooow'>Manu Wallner</a></h4>
137
+ <h4 align='center'><a href='https://twitter.com/endocrimes'>Danielle Tomlinson</a></h4>
138
+ </td>
139
+ <td id='matthew-ellis'>
140
+ <a href='https://github.com/matthewellis'>
141
+ <img src='https://github.com/matthewellis.png?size=140'>
142
+ </a>
143
+ <h4 align='center'><a href='https://twitter.com/mellis1995'>Matthew Ellis</a></h4>
150
144
  </td>
151
145
  <td id='aaron-brager'>
152
146
  <a href='https://github.com/getaaron'>
@@ -154,25 +148,31 @@ If the above doesn't help, please [submit an issue](https://github.com/fastlane/
154
148
  </a>
155
149
  <h4 align='center'><a href='https://twitter.com/getaaron'>Aaron Brager</a></h4>
156
150
  </td>
157
- <td id='matthew-ellis'>
158
- <a href='https://github.com/matthewellis'>
159
- <img src='https://github.com/matthewellis.png?size=140'>
151
+ <td id='helmut-januschka'>
152
+ <a href='https://github.com/hjanuschka'>
153
+ <img src='https://github.com/hjanuschka.png?size=140'>
160
154
  </a>
161
- <h4 align='center'><a href='https://twitter.com/mellis1995'>Matthew Ellis</a></h4>
155
+ <h4 align='center'><a href='https://twitter.com/hjanuschka'>Helmut Januschka</a></h4>
156
+ </td>
157
+ <td id='felix-krause'>
158
+ <a href='https://github.com/KrauseFx'>
159
+ <img src='https://github.com/KrauseFx.png?size=140'>
160
+ </a>
161
+ <h4 align='center'><a href='https://twitter.com/KrauseFx'>Felix Krause</a></h4>
162
162
  </td>
163
163
  </tr>
164
164
  <tr>
165
- <td id='maksym-grebenets'>
166
- <a href='https://github.com/mgrebenets'>
167
- <img src='https://github.com/mgrebenets.png?size=140'>
165
+ <td id='iulian-onofrei'>
166
+ <a href='https://github.com/revolter'>
167
+ <img src='https://github.com/revolter.png?size=140'>
168
168
  </a>
169
- <h4 align='center'><a href='https://twitter.com/mgrebenets'>Maksym Grebenets</a></h4>
169
+ <h4 align='center'><a href='https://twitter.com/Revolt666'>Iulian Onofrei</a></h4>
170
170
  </td>
171
- <td id='danielle-tomlinson'>
172
- <a href='https://github.com/endocrimes'>
173
- <img src='https://github.com/endocrimes.png?size=140'>
171
+ <td id='jérôme-lacoste'>
172
+ <a href='https://github.com/lacostej'>
173
+ <img src='https://github.com/lacostej.png?size=140'>
174
174
  </a>
175
- <h4 align='center'><a href='https://twitter.com/endocrimes'>Danielle Tomlinson</a></h4>
175
+ <h4 align='center'><a href='https://twitter.com/lacostej'>Jérôme Lacoste</a></h4>
176
176
  </td>
177
177
  </table>
178
178
 
@@ -1,3 +1,4 @@
1
+ require_relative 'deliver/languages'
1
2
  require_relative 'deliver/loader'
2
3
  require_relative 'deliver/options'
3
4
  require_relative 'deliver/commands_generator'
@@ -13,14 +13,14 @@ module Deliver
13
13
  # @yield [localization, app_screenshot_set]
14
14
  # @yieldparam [optional, Spaceship::ConnectAPI::AppStoreVersionLocalization] localization
15
15
  # @yieldparam [optional, Spaceship::ConnectAPI::AppStoreScreenshotSet] app_screenshot_set
16
- def each_app_screenshot_set(&block)
17
- return enum_for(__method__) unless block_given?
16
+ def each_app_screenshot_set(localizations = @localizations, &block)
17
+ return enum_for(__method__, localizations) unless block_given?
18
18
 
19
19
  # Collect app_screenshot_sets from localizations in parallel but
20
20
  # limit the number of threads working at a time with using `lazy` and `force` controls
21
21
  # to not attack App Store Connect
22
- results = @localizations.each_slice(NUMBER_OF_THREADS).lazy.map do |localizations|
23
- localizations.map do |localization|
22
+ results = localizations.each_slice(NUMBER_OF_THREADS).lazy.map do |localizations_grouped|
23
+ localizations_grouped.map do |localization|
24
24
  Thread.new do
25
25
  [localization, localization.get_app_screenshot_sets]
26
26
  end
@@ -63,35 +63,32 @@ module Deliver
63
63
  def each_local_screenshot(screenshots_per_language, &block)
64
64
  return enum_for(__method__, screenshots_per_language) unless block_given?
65
65
 
66
- # Iterate over all the screenshots per language and display_type
67
- # and then enqueue them to worker one by one if it's not duplciated on App Store Connect
68
- screenshots_per_language.map do |language, screenshots_for_language|
69
- localization = @localizations.find { |l| l.locale == language }
70
- [localization, screenshots_for_language]
71
- end.reject do |localization, _|
72
- localization.nil?
73
- end.each do |localization, screenshots_for_language|
74
- iterate_over_screenshots_per_language(localization, screenshots_for_language, &block)
75
- end
76
- end
66
+ # filter unnecessary localizations
67
+ supported_localizations = @localizations.reject { |l| screenshots_per_language[l.locale].nil? }
77
68
 
78
- private
69
+ # build a hash that can access app_screenshot_set corresponding to given locale and display_type
70
+ # via parallelized each_app_screenshot_set to gain performance
71
+ app_screenshot_set_per_locale_and_display_type = each_app_screenshot_set(supported_localizations)
72
+ .each_with_object({}) do |(localization, app_screenshot_set), hash|
73
+ hash[localization.locale] ||= {}
74
+ hash[localization.locale][app_screenshot_set.screenshot_display_type] = app_screenshot_set
75
+ end
79
76
 
80
- def iterate_over_screenshots_per_language(localization, screenshots_for_language, &block)
81
- app_screenshot_sets_per_display_type = localization.get_app_screenshot_sets.map { |set| [set.screenshot_display_type, set] }.to_h
82
- screenshots_per_display_type = screenshots_for_language.reject { |screenshot| screenshot.device_type.nil? }.group_by(&:device_type)
77
+ # iterate over screenshots per localization
78
+ screenshots_per_language.each do |language, screenshots_for_language|
79
+ localization = supported_localizations.find { |l| l.locale == language }
80
+ screenshots_per_display_type = screenshots_for_language.reject { |screenshot| screenshot.device_type.nil? }.group_by(&:device_type)
83
81
 
84
- screenshots_per_display_type.each do |display_type, screenshots|
85
- # Create AppScreenshotSet for given display_type if it doesn't exsit
86
- app_screenshot_set = app_screenshot_sets_per_display_type[display_type]
87
- app_screenshot_set ||= localization.create_app_screenshot_set(attributes: { screenshotDisplayType: display_type })
88
- iterate_over_screenshots_per_display_type(localization, app_screenshot_set, screenshots, &block)
89
- end
90
- end
82
+ screenshots_per_display_type.each do |display_type, screenshots|
83
+ # create AppScreenshotSet for given display_type if it doesn't exsit
84
+ app_screenshot_set = app_screenshot_set_per_locale_and_display_type[language][display_type]
85
+ app_screenshot_set ||= localization.create_app_screenshot_set(attributes: { screenshotDisplayType: display_type })
91
86
 
92
- def iterate_over_screenshots_per_display_type(localization, app_screenshot_set, screenshots, &block)
93
- screenshots.each.with_index do |screenshot, index|
94
- yield(localization, app_screenshot_set, screenshot, index)
87
+ # iterate over screenshots per display size with index
88
+ screenshots.each.with_index do |screenshot, index|
89
+ yield(localization, app_screenshot_set, screenshot, index)
90
+ end
91
+ end
95
92
  end
96
93
  end
97
94
  end
@@ -5,6 +5,7 @@ require 'spaceship/tunes/tunes'
5
5
  require 'spaceship/tunes/application'
6
6
 
7
7
  require_relative 'module'
8
+ require_relative 'languages'
8
9
 
9
10
  module Deliver
10
11
  class DetectValues
@@ -88,7 +89,9 @@ module Deliver
88
89
  languages = options[:languages]
89
90
  return unless languages
90
91
 
91
- all_languages = Spaceship::Tunes.client.available_languages
92
+ # 2020-08-24 - Available locales are not available as an endpoint in App Store Connect
93
+ # Update with Spaceship::Tunes.client.available_languages.sort (as long as endpoint is avilable)
94
+ all_languages = Deliver::Languages::ALL_LANGUAGES
92
95
  diff = languages - all_languages
93
96
 
94
97
  unless diff.empty?
@@ -0,0 +1,7 @@
1
+ module Deliver
2
+ module Languages
3
+ # 2020-08-24 - Available locales are not available as an endpoint in App Store Connect
4
+ # Update with Spaceship::Tunes.client.available_languages.sort (as long as endpoint is avilable)
5
+ ALL_LANGUAGES = ["ar-SA", "ca", "cs", "da", "de-DE", "el", "en-AU", "en-CA", "en-GB", "en-US", "es-ES", "es-MX", "fi", "fr-CA", "fr-FR", "he", "hi", "hr", "hu", "id", "it", "ja", "ko", "ms", "nl-NL", "no", "pl", "pt-BR", "pt-PT", "ro", "ru", "sk", "sv", "th", "tr", "uk", "vi", "zh-Hans", "zh-Hant"]
6
+ end
7
+ end
@@ -3,6 +3,7 @@ require 'spaceship/tunes/tunes'
3
3
 
4
4
  require_relative 'module'
5
5
  require_relative 'upload_metadata'
6
+ require_relative 'languages'
6
7
 
7
8
  module Deliver
8
9
  module Loader
@@ -24,11 +25,9 @@ module Deliver
24
25
  def self.language_folders(root, ignore_validation)
25
26
  folders = Dir.glob(File.join(root, '*'))
26
27
 
27
- if Helper.test?
28
- available_languages = FastlaneCore::Languages::ALL_LANGUAGES
29
- else
30
- available_languages = Spaceship::Tunes.client.available_languages.sort
31
- end
28
+ # 2020-08-24 - Available locales are not available as an endpoint in App Store Connect
29
+ # Update with Spaceship::Tunes.client.available_languages.sort (as long as endpoint is avilable)
30
+ available_languages = Deliver::Languages::ALL_LANGUAGES
32
31
 
33
32
  allowed_directory_names_with_case = (available_languages + SPECIAL_DIR_NAMES)
34
33
  allowed_directory_names = allowed_directory_names_with_case.map(&:downcase).freeze
@@ -27,8 +27,8 @@ module Deliver
27
27
 
28
28
  def login
29
29
  UI.message("Login to App Store Connect (#{options[:username]})")
30
- Spaceship::Tunes.login(options[:username])
31
- Spaceship::Tunes.select_team
30
+ Spaceship::ConnectAPI.login(options[:username])
31
+ Spaceship::ConnectAPI.select_team
32
32
  UI.message("Login successful")
33
33
  end
34
34
 
@@ -177,17 +177,19 @@ module Deliver
177
177
  # If there are multiple teams, infer the provider from the selected team name.
178
178
  # If there are fewer than two teams, don't infer the provider.
179
179
  def transporter_for_selected_team
180
+ tunes_client = Spaceship::ConnectAPI.client.tunes_client
181
+
180
182
  generic_transporter = FastlaneCore::ItunesTransporter.new(options[:username], nil, false, options[:itc_provider])
181
- return generic_transporter unless options[:itc_provider].nil? && Spaceship::Tunes.client.teams.count > 1
183
+ return generic_transporter unless options[:itc_provider].nil? && tunes_client.teams.count > 1
182
184
 
183
185
  begin
184
- team = Spaceship::Tunes.client.teams.find { |t| t['contentProvider']['contentProviderId'].to_s == Spaceship::Tunes.client.team_id }
186
+ team = tunes_client.teams.find { |t| t['contentProvider']['contentProviderId'].to_s == tunes_client.team_id }
185
187
  name = team['contentProvider']['name']
186
188
  provider_id = generic_transporter.provider_ids[name]
187
189
  UI.verbose("Inferred provider id #{provider_id} for team #{name}.")
188
190
  return FastlaneCore::ItunesTransporter.new(options[:username], nil, false, provider_id)
189
191
  rescue => ex
190
- UI.verbose("Couldn't infer a provider short name for team with id #{Spaceship::Tunes.client.team_id} automatically: #{ex}. Proceeding without provider short name.")
192
+ UI.verbose("Couldn't infer a provider short name for team with id #{tunes_client.team_id} automatically: #{ex}. Proceeding without provider short name.")
191
193
  return generic_transporter
192
194
  end
193
195
  end
@@ -179,21 +179,40 @@ module Deliver
179
179
  # Verify all screenshots states on App Store Connect are okay
180
180
  def retry_upload_screenshots_if_needed(iterator, states, number_of_screenshots, tries, localizations, screenshots_per_language)
181
181
  is_failure = states.fetch("FAILED", 0) > 0
182
- is_missing_screenshot = states.reduce(0) { |sum, (k, v)| sum + v } != number_of_screenshots && !screenshots_per_language.empty?
182
+ is_missing_screenshot = !screenshots_per_language.empty? && !verify_local_screenshots_are_uploaded(iterator, screenshots_per_language)
183
+ return unless is_failure || is_missing_screenshot
183
184
 
184
- if is_failure || is_missing_screenshot
185
- if tries.zero?
186
- incomplete_screenshot_count = states.reject { |k, v| k == 'COMPLETE' }.reduce(0) { |sum, (k, v)| sum + v }
187
- UI.user_error!("Failed verification of all screenshots uploaded... #{incomplete_screenshot_count} incomplete screenshot(s) still exist")
188
- else
189
- UI.error("Failed to upload all screenshots... Tries remaining: #{tries}")
190
- # Delete bad entries before retry
191
- iterator.each_app_screenshot do |_, _, app_screenshot|
192
- app_screenshot.delete! unless app_screenshot.complete?
193
- end
194
- upload_screenshots(localizations, screenshots_per_language, tries: tries)
185
+ if tries.zero?
186
+ iterator.each_app_screenshot.select { |_, _, app_screenshot| app_screenshot.error? }.each do |localization, _, app_screenshot|
187
+ UI.error("#{app_screenshot.file_name} for #{localization.locale} has error(s) - #{app_screenshot.error_messages.join(', ')}")
195
188
  end
189
+ incomplete_screenshot_count = states.reject { |k, v| k == 'COMPLETE' }.reduce(0) { |sum, (k, v)| sum + v }
190
+ UI.user_error!("Failed verification of all screenshots uploaded... #{incomplete_screenshot_count} incomplete screenshot(s) still exist")
191
+ else
192
+ UI.error("Failed to upload all screenshots... Tries remaining: #{tries}")
193
+ # Delete bad entries before retry
194
+ iterator.each_app_screenshot do |_, _, app_screenshot|
195
+ app_screenshot.delete! unless app_screenshot.complete?
196
+ end
197
+ upload_screenshots(localizations, screenshots_per_language, tries: tries)
198
+ end
199
+ end
200
+
201
+ # Return `true` if all the local screenshots are uploaded to App Store Connect
202
+ def verify_local_screenshots_are_uploaded(iterator, screenshots_per_language)
203
+ # Check if local screenshots' checksum exist on App Store Connect
204
+ checksum_to_app_screenshot = iterator.each_app_screenshot.map { |_, _, app_screenshot| [app_screenshot.source_file_checksum, app_screenshot] }.to_h
205
+
206
+ missing_local_screenshots = iterator.each_local_screenshot(screenshots_per_language).select do |_, _, local_screenshot, index|
207
+ checksum = UploadScreenshots.calculate_checksum(local_screenshot.path)
208
+ checksum_to_app_screenshot[checksum].nil? && index < 10 # if index is more than 10, it's skipped
209
+ end
210
+
211
+ missing_local_screenshots.each do |_, _, screenshot, _|
212
+ UI.error("#{screenshot.path} is missing on App Store Connect.")
196
213
  end
214
+
215
+ missing_local_screenshots.empty?
197
216
  end
198
217
 
199
218
  def sort_screenshots(localizations)
@@ -285,11 +304,9 @@ module Deliver
285
304
 
286
305
  # helper method so Spaceship::Tunes.client.available_languages is easier to test
287
306
  def self.available_languages
288
- if Helper.test?
289
- FastlaneCore::Languages::ALL_LANGUAGES
290
- else
291
- Spaceship::Tunes.client.available_languages
292
- end
307
+ # 2020-08-24 - Available locales are not available as an endpoint in App Store Connect
308
+ # Update with Spaceship::Tunes.client.available_languages.sort (as long as endpoint is avilable)
309
+ Deliver::Languages::ALL_LANGUAGES
293
310
  end
294
311
 
295
312
  # helper method to mock this step in tests