fastlane 2.234.0 → 2.235.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 (71) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +100 -100
  3. data/bin/fastlane +2 -2
  4. data/deliver/lib/deliver/app_clip_header_image.rb +18 -0
  5. data/deliver/lib/deliver/commands_generator.rb +17 -0
  6. data/deliver/lib/deliver/download_app_clip_header_images.rb +64 -0
  7. data/deliver/lib/deliver/languages.rb +36 -3
  8. data/deliver/lib/deliver/loader.rb +41 -0
  9. data/deliver/lib/deliver/options.rb +23 -0
  10. data/deliver/lib/deliver/runner.rb +8 -0
  11. data/deliver/lib/deliver/upload_app_clip_default_experience_header_images.rb +188 -0
  12. data/deliver/lib/deliver/upload_app_clip_default_experience_metadata.rb +229 -0
  13. data/deliver/lib/deliver/upload_metadata.rb +71 -7
  14. data/deliver/lib/deliver/upload_screenshots.rb +1 -1
  15. data/fastlane/lib/fastlane/actions/docs/upload_to_app_store.md.erb +100 -0
  16. data/fastlane/lib/fastlane/actions/get_version_number.rb +2 -12
  17. data/fastlane/lib/fastlane/actions/increment_version_number.rb +29 -1
  18. data/fastlane/lib/fastlane/actions/ipa.rb +2 -2
  19. data/fastlane/lib/fastlane/actions/notarize.rb +1 -148
  20. data/fastlane/lib/fastlane/actions/slack.rb +9 -3
  21. data/fastlane/lib/fastlane/actions/testfairy.rb +1 -3
  22. data/fastlane/lib/fastlane/documentation/markdown_docs_generator.rb +3 -1
  23. data/fastlane/lib/fastlane/helper/xcodeproj_helper.rb +155 -0
  24. data/fastlane/lib/fastlane/notification/slack.rb +9 -4
  25. data/fastlane/lib/fastlane/plugins/template/%gem_name%.gemspec.erb +1 -1
  26. data/fastlane/lib/fastlane/plugins/template/.rubocop.yml +1 -1
  27. data/fastlane/lib/fastlane/version.rb +1 -1
  28. data/fastlane/swift/Deliverfile.swift +1 -1
  29. data/fastlane/swift/DeliverfileProtocol.swift +36 -1
  30. data/fastlane/swift/Fastlane.swift +89 -9
  31. data/fastlane/swift/Gymfile.swift +1 -1
  32. data/fastlane/swift/GymfileProtocol.swift +1 -1
  33. data/fastlane/swift/Matchfile.swift +1 -1
  34. data/fastlane/swift/MatchfileProtocol.swift +1 -1
  35. data/fastlane/swift/Precheckfile.swift +1 -1
  36. data/fastlane/swift/PrecheckfileProtocol.swift +1 -1
  37. data/fastlane/swift/Scanfile.swift +1 -1
  38. data/fastlane/swift/ScanfileProtocol.swift +1 -1
  39. data/fastlane/swift/Screengrabfile.swift +1 -1
  40. data/fastlane/swift/ScreengrabfileProtocol.swift +1 -1
  41. data/fastlane/swift/Snapshotfile.swift +1 -1
  42. data/fastlane/swift/SnapshotfileProtocol.swift +1 -1
  43. data/fastlane_core/lib/fastlane_core/command_executor.rb +13 -5
  44. data/frameit/lib/frameit/offsets.rb +3 -2
  45. data/internal/README.md +11 -0
  46. data/match/lib/match/nuke.rb +2 -2
  47. data/pilot/lib/pilot/build_manager.rb +69 -2
  48. data/pilot/lib/pilot/options.rb +23 -0
  49. data/screengrab/lib/screengrab/reports_generator.rb +2 -2
  50. data/screengrab/lib/screengrab/runner.rb +14 -15
  51. data/sigh/lib/sigh/resign.rb +2 -2
  52. data/snapshot/lib/snapshot/reports_generator.rb +2 -2
  53. data/snapshot/lib/snapshot/simulator_launchers/simulator_launcher_base.rb +9 -9
  54. data/spaceship/lib/spaceship/connect_api/models/app.rb +14 -1
  55. data/spaceship/lib/spaceship/connect_api/models/app_clip.rb +18 -0
  56. data/spaceship/lib/spaceship/connect_api/models/app_clip_app_store_review_detail.rb +34 -0
  57. data/spaceship/lib/spaceship/connect_api/models/app_clip_default_experience.rb +43 -0
  58. data/spaceship/lib/spaceship/connect_api/models/app_clip_default_experience_localization.rb +49 -0
  59. data/spaceship/lib/spaceship/connect_api/models/app_clip_header_image.rb +159 -0
  60. data/spaceship/lib/spaceship/connect_api/models/app_store_version.rb +5 -1
  61. data/spaceship/lib/spaceship/connect_api/models/beta_app_clip_invocation.rb +44 -0
  62. data/spaceship/lib/spaceship/connect_api/models/beta_app_clip_invocation_localization.rb +35 -0
  63. data/spaceship/lib/spaceship/connect_api/models/build_bundle.rb +1 -1
  64. data/spaceship/lib/spaceship/connect_api/tunes/tunes.rb +291 -0
  65. data/spaceship/lib/spaceship/connect_api.rb +7 -0
  66. data/spaceship/lib/spaceship/portal/portal_client.rb +1 -1
  67. data/spaceship/lib/spaceship/two_step_or_factor_client.rb +2 -1
  68. data/supply/lib/supply/client.rb +14 -19
  69. data/supply/lib/supply/reader.rb +16 -0
  70. data/supply/lib/supply/uploader.rb +1 -1
  71. metadata +41 -29
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 525a3a4fbaab6476e3908604bbe7961491cb337a2a389a4ddd5d42248b9ff05c
4
- data.tar.gz: 1fc064f5f314cebf73705bc011a6074e458b87ba5b2b0d34296f57b6d14a83c7
3
+ metadata.gz: 14907c8841271cfdc5ca71eeb8b413b39772478ec3691d1301fb1c4432dc9768
4
+ data.tar.gz: eaf7da1b6040142a160972fe8f42a88bf4c10912375b217877262cba144707c0
5
5
  SHA512:
6
- metadata.gz: 9b9d73f37397f4f03ada825e099f3904adb879133c7c777a95418e8898922ef3d04b2594c1db5e95cfb34e202f9d493ba613428deccfaacc7401dbe2a941f95b
7
- data.tar.gz: db0c73f50e6c6e8d745944739ab3f0c86bdc6328026c03eed1dae1d0402031553af1d506e970206438df4638d64b32c15b7321295929ffd9ed98c936691d6d93
6
+ metadata.gz: 29080ed1e5e25292a2a95dd9ae6e1def90246c84d4331d78a153818fc73f8bf1f67ee7a886e0e54b67966ffcf72c462088d197f213ca5e2d71f94c701146f4db
7
+ data.tar.gz: 5bdea3d658146484366f97e4a52a301e0ec0a6aa203b616fc35676846865b27d3a9d1789991907639179268fc1b77ed24387c1ea82792e71945d17dff9af8480
data/README.md CHANGED
@@ -36,29 +36,11 @@ If the above doesn't help, please [submit an issue](https://github.com/fastlane/
36
36
  <!-- This table is regenerated and resorted on each release -->
37
37
  <table id='team'>
38
38
  <tr>
39
- <td id='joshua-liebowitz'>
40
- <a href='https://github.com/taquitos'>
41
- <img src='https://github.com/taquitos.png' width='140px;'>
42
- </a>
43
- <h4 align='center'><a href='https://twitter.com/taquitos'>Joshua Liebowitz</a></h4>
44
- </td>
45
- <td id='manish-rathi'>
46
- <a href='https://github.com/crazymanish'>
47
- <img src='https://github.com/crazymanish.png' width='140px;'>
48
- </a>
49
- <h4 align='center'><a href='https://twitter.com/iammanishrathi'>Manish Rathi</a></h4>
50
- </td>
51
- <td id='josh-holtz'>
52
- <a href='https://github.com/joshdholtz'>
53
- <img src='https://github.com/joshdholtz.png' width='140px;'>
54
- </a>
55
- <h4 align='center'><a href='https://twitter.com/joshdholtz'>Josh Holtz</a></h4>
56
- </td>
57
- <td id='satoshi-namai'>
58
- <a href='https://github.com/ainame'>
59
- <img src='https://github.com/ainame.png' width='140px;'>
39
+ <td id='jimmy-dee'>
40
+ <a href='https://github.com/jdee'>
41
+ <img src='https://github.com/jdee.png' width='140px;'>
60
42
  </a>
61
- <h4 align='center'><a href='https://twitter.com/ainame'>Satoshi Namai</a></h4>
43
+ <h4 align='center'>Jimmy Dee</h4>
62
44
  </td>
63
45
  <td id='jérôme-lacoste'>
64
46
  <a href='https://github.com/lacostej'>
@@ -66,19 +48,63 @@ If the above doesn't help, please [submit an issue](https://github.com/fastlane/
66
48
  </a>
67
49
  <h4 align='center'><a href='https://twitter.com/lacostej'>Jérôme Lacoste</a></h4>
68
50
  </td>
69
- </tr>
70
- <tr>
51
+ <td id='stefan-natchev'>
52
+ <a href='https://github.com/snatchev'>
53
+ <img src='https://github.com/snatchev.png' width='140px;'>
54
+ </a>
55
+ <h4 align='center'><a href='https://twitter.com/snatchev'>Stefan Natchev</a></h4>
56
+ </td>
71
57
  <td id='kohki-miki'>
72
58
  <a href='https://github.com/giginet'>
73
59
  <img src='https://github.com/giginet.png' width='140px;'>
74
60
  </a>
75
61
  <h4 align='center'><a href='https://twitter.com/giginet'>Kohki Miki</a></h4>
76
62
  </td>
77
- <td id='maksym-grebenets'>
78
- <a href='https://github.com/mgrebenets'>
79
- <img src='https://github.com/mgrebenets.png' width='140px;'>
63
+ <td id='iulian-onofrei'>
64
+ <a href='https://github.com/revolter'>
65
+ <img src='https://github.com/revolter.png' width='140px;'>
80
66
  </a>
81
- <h4 align='center'><a href='https://twitter.com/mgrebenets'>Maksym Grebenets</a></h4>
67
+ <h4 align='center'><a href='https://twitter.com/Revolt666'>Iulian Onofrei</a></h4>
68
+ </td>
69
+ </tr>
70
+ <tr>
71
+ <td id='manu-wallner'>
72
+ <a href='https://github.com/milch'>
73
+ <img src='https://github.com/milch.png' width='140px;'>
74
+ </a>
75
+ <h4 align='center'><a href='https://twitter.com/acrooow'>Manu Wallner</a></h4>
76
+ </td>
77
+ <td id='helmut-januschka'>
78
+ <a href='https://github.com/hjanuschka'>
79
+ <img src='https://github.com/hjanuschka.png' width='140px;'>
80
+ </a>
81
+ <h4 align='center'><a href='https://twitter.com/hjanuschka'>Helmut Januschka</a></h4>
82
+ </td>
83
+ <td id='roger-oba'>
84
+ <a href='https://github.com/rogerluan'>
85
+ <img src='https://github.com/rogerluan.png' width='140px;'>
86
+ </a>
87
+ <h4 align='center'><a href='https://twitter.com/rogerluan_'>Roger Oba</a></h4>
88
+ </td>
89
+ <td id='fumiya-nakamura'>
90
+ <a href='https://github.com/nafu'>
91
+ <img src='https://github.com/nafu.png' width='140px;'>
92
+ </a>
93
+ <h4 align='center'><a href='https://twitter.com/nafu003'>Fumiya Nakamura</a></h4>
94
+ </td>
95
+ <td id='manish-rathi'>
96
+ <a href='https://github.com/crazymanish'>
97
+ <img src='https://github.com/crazymanish.png' width='140px;'>
98
+ </a>
99
+ <h4 align='center'><a href='https://twitter.com/iammanishrathi'>Manish Rathi</a></h4>
100
+ </td>
101
+ </tr>
102
+ <tr>
103
+ <td id='max-ott'>
104
+ <a href='https://github.com/max-ott'>
105
+ <img src='https://github.com/max-ott.png' width='140px;'>
106
+ </a>
107
+ <h4 align='center'><a href='https://twitter.com/ott_max'>Max Ott</a></h4>
82
108
  </td>
83
109
  <td id='olivier-halligon'>
84
110
  <a href='https://github.com/AliSoftware'>
@@ -86,57 +112,69 @@ If the above doesn't help, please [submit an issue](https://github.com/fastlane/
86
112
  </a>
87
113
  <h4 align='center'><a href='https://twitter.com/aligatr'>Olivier Halligon</a></h4>
88
114
  </td>
89
- <td id='matthew-ellis'>
90
- <a href='https://github.com/matthewellis'>
91
- <img src='https://github.com/matthewellis.png' width='140px;'>
92
- </a>
93
- <h4 align='center'><a href='https://twitter.com/mellis1995'>Matthew Ellis</a></h4>
94
- </td>
95
115
  <td id='daniel-jankowski'>
96
116
  <a href='https://github.com/mollyIV'>
97
117
  <img src='https://github.com/mollyIV.png' width='140px;'>
98
118
  </a>
99
119
  <h4 align='center'><a href='https://twitter.com/mollyIV'>Daniel Jankowski</a></h4>
100
120
  </td>
101
- </tr>
102
- <tr>
103
- <td id='connor-tumbleson'>
104
- <a href='https://github.com/ibotpeaches'>
105
- <img src='https://github.com/ibotpeaches.png' width='140px;'>
121
+ <td id='andrew-mcburney'>
122
+ <a href='https://github.com/armcburney'>
123
+ <img src='https://github.com/armcburney.png' width='140px;'>
106
124
  </a>
107
- <h4 align='center'><a href='https://twitter.com/ibotpeaches'>Connor Tumbleson</a></h4>
125
+ <h4 align='center'><a href='https://twitter.com/armcburney'>Andrew McBurney</a></h4>
108
126
  </td>
109
- <td id='jan-piotrowski'>
110
- <a href='https://github.com/janpio'>
111
- <img src='https://github.com/janpio.png' width='140px;'>
127
+ <td id='maksym-grebenets'>
128
+ <a href='https://github.com/mgrebenets'>
129
+ <img src='https://github.com/mgrebenets.png' width='140px;'>
112
130
  </a>
113
- <h4 align='center'><a href='https://twitter.com/Sujan'>Jan Piotrowski</a></h4>
131
+ <h4 align='center'><a href='https://twitter.com/mgrebenets'>Maksym Grebenets</a></h4>
114
132
  </td>
133
+ </tr>
134
+ <tr>
115
135
  <td id='jorge-revuelta-h'>
116
136
  <a href='https://github.com/minuscorp'>
117
137
  <img src='https://github.com/minuscorp.png' width='140px;'>
118
138
  </a>
119
139
  <h4 align='center'><a href='https://twitter.com/minuscorp'>Jorge Revuelta H</a></h4>
120
140
  </td>
121
- <td id='max-ott'>
122
- <a href='https://github.com/max-ott'>
123
- <img src='https://github.com/max-ott.png' width='140px;'>
141
+ <td id='aaron-brager'>
142
+ <a href='https://github.com/getaaron'>
143
+ <img src='https://github.com/getaaron.png' width='140px;'>
124
144
  </a>
125
- <h4 align='center'><a href='https://twitter.com/ott_max'>Max Ott</a></h4>
145
+ <h4 align='center'><a href='https://twitter.com/getaaron'>Aaron Brager</a></h4>
146
+ </td>
147
+ <td id='josh-holtz'>
148
+ <a href='https://github.com/joshdholtz'>
149
+ <img src='https://github.com/joshdholtz.png' width='140px;'>
150
+ </a>
151
+ <h4 align='center'><a href='https://twitter.com/joshdholtz'>Josh Holtz</a></h4>
152
+ </td>
153
+ <td id='satoshi-namai'>
154
+ <a href='https://github.com/ainame'>
155
+ <img src='https://github.com/ainame.png' width='140px;'>
156
+ </a>
157
+ <h4 align='center'><a href='https://twitter.com/ainame'>Satoshi Namai</a></h4>
126
158
  </td>
159
+ <td id='matthew-ellis'>
160
+ <a href='https://github.com/matthewellis'>
161
+ <img src='https://github.com/matthewellis.png' width='140px;'>
162
+ </a>
163
+ <h4 align='center'><a href='https://twitter.com/mellis1995'>Matthew Ellis</a></h4>
164
+ </td>
165
+ </tr>
166
+ <tr>
127
167
  <td id='luka-mirosevic'>
128
168
  <a href='https://github.com/lmirosevic'>
129
169
  <img src='https://github.com/lmirosevic.png' width='140px;'>
130
170
  </a>
131
171
  <h4 align='center'><a href='https://twitter.com/lmirosevic'>Luka Mirosevic</a></h4>
132
172
  </td>
133
- </tr>
134
- <tr>
135
- <td id='fumiya-nakamura'>
136
- <a href='https://github.com/nafu'>
137
- <img src='https://github.com/nafu.png' width='140px;'>
173
+ <td id='connor-tumbleson'>
174
+ <a href='https://github.com/ibotpeaches'>
175
+ <img src='https://github.com/ibotpeaches.png' width='140px;'>
138
176
  </a>
139
- <h4 align='center'><a href='https://twitter.com/nafu003'>Fumiya Nakamura</a></h4>
177
+ <h4 align='center'><a href='https://twitter.com/ibotpeaches'>Connor Tumbleson</a></h4>
140
178
  </td>
141
179
  <td id='danielle-tomlinson'>
142
180
  <a href='https://github.com/endocrimes'>
@@ -150,31 +188,19 @@ If the above doesn't help, please [submit an issue](https://github.com/fastlane/
150
188
  </a>
151
189
  <h4 align='center'><a href='https://twitter.com/KrauseFx'>Felix Krause</a></h4>
152
190
  </td>
153
- <td id='stefan-natchev'>
154
- <a href='https://github.com/snatchev'>
155
- <img src='https://github.com/snatchev.png' width='140px;'>
156
- </a>
157
- <h4 align='center'><a href='https://twitter.com/snatchev'>Stefan Natchev</a></h4>
158
- </td>
159
- <td id='aaron-brager'>
160
- <a href='https://github.com/getaaron'>
161
- <img src='https://github.com/getaaron.png' width='140px;'>
191
+ <td id='joshua-liebowitz'>
192
+ <a href='https://github.com/taquitos'>
193
+ <img src='https://github.com/taquitos.png' width='140px;'>
162
194
  </a>
163
- <h4 align='center'><a href='https://twitter.com/getaaron'>Aaron Brager</a></h4>
195
+ <h4 align='center'><a href='https://twitter.com/taquitos'>Joshua Liebowitz</a></h4>
164
196
  </td>
165
197
  </tr>
166
198
  <tr>
167
- <td id='manu-wallner'>
168
- <a href='https://github.com/milch'>
169
- <img src='https://github.com/milch.png' width='140px;'>
170
- </a>
171
- <h4 align='center'><a href='https://twitter.com/acrooow'>Manu Wallner</a></h4>
172
- </td>
173
- <td id='andrew-mcburney'>
174
- <a href='https://github.com/armcburney'>
175
- <img src='https://github.com/armcburney.png' width='140px;'>
199
+ <td id='jan-piotrowski'>
200
+ <a href='https://github.com/janpio'>
201
+ <img src='https://github.com/janpio.png' width='140px;'>
176
202
  </a>
177
- <h4 align='center'><a href='https://twitter.com/armcburney'>Andrew McBurney</a></h4>
203
+ <h4 align='center'><a href='https://twitter.com/Sujan'>Jan Piotrowski</a></h4>
178
204
  </td>
179
205
  <td id='łukasz-grabowski'>
180
206
  <a href='https://github.com/lucgrabowski'>
@@ -182,32 +208,6 @@ If the above doesn't help, please [submit an issue](https://github.com/fastlane/
182
208
  </a>
183
209
  <h4 align='center'>Łukasz Grabowski</h4>
184
210
  </td>
185
- <td id='jimmy-dee'>
186
- <a href='https://github.com/jdee'>
187
- <img src='https://github.com/jdee.png' width='140px;'>
188
- </a>
189
- <h4 align='center'>Jimmy Dee</h4>
190
- </td>
191
- <td id='helmut-januschka'>
192
- <a href='https://github.com/hjanuschka'>
193
- <img src='https://github.com/hjanuschka.png' width='140px;'>
194
- </a>
195
- <h4 align='center'><a href='https://twitter.com/hjanuschka'>Helmut Januschka</a></h4>
196
- </td>
197
- </tr>
198
- <tr>
199
- <td id='roger-oba'>
200
- <a href='https://github.com/rogerluan'>
201
- <img src='https://github.com/rogerluan.png' width='140px;'>
202
- </a>
203
- <h4 align='center'><a href='https://twitter.com/rogerluan_'>Roger Oba</a></h4>
204
- </td>
205
- <td id='iulian-onofrei'>
206
- <a href='https://github.com/revolter'>
207
- <img src='https://github.com/revolter.png' width='140px;'>
208
- </a>
209
- <h4 align='center'><a href='https://twitter.com/Revolt666'>Iulian Onofrei</a></h4>
210
- </td>
211
211
  </table>
212
212
 
213
213
  Special thanks to all [contributors](https://github.com/fastlane/fastlane/graphs/contributors) for extending and improving _fastlane_.
data/bin/fastlane CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- if RUBY_VERSION < '2.7.0'
4
- abort("fastlane requires Ruby 2.7.0 or higher")
3
+ if RUBY_VERSION < '3.0.0'
4
+ abort("fastlane requires Ruby 3.0.0 or higher")
5
5
  end
6
6
 
7
7
  def self.windows?
@@ -0,0 +1,18 @@
1
+ require 'fastimage'
2
+
3
+ require_relative 'module'
4
+
5
+ module Deliver
6
+ # AppClipHeaderImage represents one app clip header image for one specific locale.
7
+ class AppClipHeaderImage
8
+ attr_accessor :path
9
+ attr_accessor :language
10
+
11
+ # @param path (String) path to the app clip header image file
12
+ # @param language (String) Language of this app clip header image (e.g. en-US)
13
+ def initialize(path, language)
14
+ self.path = path
15
+ self.language = language
16
+ end
17
+ end
18
+ end
@@ -3,6 +3,7 @@ require 'fastlane/version'
3
3
  require 'fastlane_core/ui/help_formatter'
4
4
 
5
5
  require_relative 'download_screenshots'
6
+ require_relative 'download_app_clip_header_images'
6
7
  require_relative 'options'
7
8
  require_relative 'module'
8
9
  require_relative 'generate_summary'
@@ -152,6 +153,22 @@ module Deliver
152
153
  end
153
154
  end
154
155
 
156
+ command :download_app_clip_header_images do |c|
157
+ c.syntax = 'fastlane deliver download_app_clip_header_images'
158
+ c.description = "Downloads all existing app clip header images from App Store Connect and stores them in the app_clip_header_images folder"
159
+
160
+ FastlaneCore::CommanderGenerator.new.generate(deliverfile_options, command: c)
161
+
162
+ c.action do |args, options|
163
+ options = FastlaneCore::Configuration.create(deliverfile_options(skip_verification: true), options.__hash__)
164
+ options.load_configuration_file("Deliverfile")
165
+ Deliver::Runner.new(options, skip_version: true) # to login...
166
+ containing = FastlaneCore::Helper.fastlane_enabled_folder_path
167
+ path = options[:app_clip_header_images_path] || File.join(containing, 'app_clip_header_images')
168
+ Deliver::DownloadAppClipHeaderImages.run(options, path)
169
+ end
170
+ end
171
+
155
172
  command :download_metadata do |c|
156
173
  c.syntax = 'fastlane deliver download_metadata'
157
174
  c.description = "Downloads existing metadata and stores it locally. This overwrites the local files."
@@ -0,0 +1,64 @@
1
+ require_relative 'module'
2
+ require 'spaceship'
3
+
4
+ module Deliver
5
+ class DownloadAppClipHeaderImages
6
+ def self.run(options, path)
7
+ UI.message("Downloading all existing app clip header images...")
8
+ download(options, path)
9
+ UI.success("Successfully downloaded all existing app clip header images")
10
+ rescue => ex
11
+ UI.error(ex)
12
+ UI.error("Couldn't download already existing app clip header images from App Store Connect.")
13
+ end
14
+
15
+ def self.download(options, folder_path)
16
+ app = Deliver.cache[:app]
17
+
18
+ platform = Spaceship::ConnectAPI::Platform.map(options[:platform])
19
+ if options[:use_live_version]
20
+ version = app.get_live_app_store_version(platform: platform, includes: Spaceship::ConnectAPI::AppStoreVersion::ESSENTIAL_INCLUDES + ",appClipDefaultExperience")
21
+ UI.user_error!("Could not find a live version on App Store Connect. Try using '--use_live_version false'") if version.nil?
22
+ else
23
+ version = app.get_edit_app_store_version(platform: platform, includes: Spaceship::ConnectAPI::AppStoreVersion::ESSENTIAL_INCLUDES + ",appClipDefaultExperience")
24
+ UI.user_error!("Could not find an edit version on App Store Connect. Try using '--use_live_version true'") if version.nil?
25
+ end
26
+
27
+ default_experience = version.app_clip_default_experience
28
+ UI.user_error!("Cannot download app clip header images if no default experience exists for version '#{version.version_string}'") unless default_experience
29
+
30
+ localizations = Spaceship::ConnectAPI::AppClipDefaultExperienceLocalization.find_all(app_clip_default_experience_id: default_experience.id, includes: 'appClipHeaderImage')
31
+
32
+ threads = []
33
+ localizations.each do |localization|
34
+ threads << Thread.new do
35
+ download_app_clip_header_image(folder_path, localization)
36
+ end
37
+ end
38
+ threads.each(&:join)
39
+ end
40
+
41
+ def self.download_app_clip_header_image(folder_path, localization)
42
+ language = localization.locale
43
+ app_clip_header_image = localization.app_clip_header_image
44
+
45
+ file_name = app_clip_header_image.file_name
46
+ original_file_extension = File.extname(file_name).strip.downcase[1..-1]
47
+
48
+ url = app_clip_header_image.image_asset_url(type: original_file_extension)
49
+ return if url.nil?
50
+
51
+ UI.message("Downloading existing app clip header image '#{file_name}' for language '#{language}'")
52
+
53
+ containing_folder = File.join(folder_path, language)
54
+ begin
55
+ FileUtils.mkdir_p(containing_folder)
56
+ rescue
57
+ # if it's already there
58
+ end
59
+
60
+ path = File.join(containing_folder, file_name)
61
+ File.binwrite(path, FastlaneCore::Helper.open_uri(url).read)
62
+ end
63
+ end
64
+ end
@@ -1,7 +1,40 @@
1
+ require 'fastlane_core/languages'
2
+
1
3
  module Deliver
2
4
  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 available)
5
- ALL_LANGUAGES = %w[ar-SA bn-BD ca cs da de-DE el en-AU en-CA en-GB en-US es-ES es-MX fi fr-CA fr-FR gu-IN he hi hr hu id it ja kn-IN ko ml-IN mr-IN ms nl-NL no or-IN pa-IN pl pt-BR pt-PT ro ru sk sl-SI sv ta-IN te-IN th tr uk ur-PK vi zh-Hans zh-Hant]
5
+ ALL_LANGUAGES = FastlaneCore::Languages::ALL_LANGUAGES
6
+
7
+ # Detects all enabled languages from various sources
8
+ # @param options [Hash] The options hash containing language settings
9
+ # @param localized_values_keys [Array<Symbol>] Keys to check for localized values in options
10
+ # @param metadata_path [String, nil] Path to metadata folder to check for language folders
11
+ # @param ignore_validation [Boolean] Whether to ignore language directory validation
12
+ # @return [Array<String>] List of unique enabled language codes
13
+ def self.detect_languages(options:, localized_values_keys: [], metadata_path: nil, ignore_validation: false)
14
+ require_relative 'loader'
15
+
16
+ enabled_languages = options[:languages] || []
17
+
18
+ # Get all languages used in existing localized settings
19
+ localized_values_keys.each do |key|
20
+ current = options[key]
21
+ next unless current && current.kind_of?(Hash)
22
+ current.each do |language, value|
23
+ enabled_languages << language unless enabled_languages.include?(language)
24
+ end
25
+ end
26
+
27
+ # Check folder list if metadata_path is provided (an empty folder signifies a language is required)
28
+ if metadata_path
29
+ Loader.language_folders(metadata_path, ignore_validation).each do |lang_folder|
30
+ enabled_languages << lang_folder.basename unless enabled_languages.include?(lang_folder.basename)
31
+ end
32
+ end
33
+
34
+ # Mapping to strings because :default symbol can be passed in
35
+ enabled_languages
36
+ .map(&:to_s)
37
+ .uniq
38
+ end
6
39
  end
7
40
  end
@@ -1,6 +1,7 @@
1
1
  require_relative 'module'
2
2
  require_relative 'app_screenshot'
3
3
  require_relative 'app_screenshot_validator'
4
+ require_relative 'app_clip_header_image'
4
5
  require_relative 'upload_metadata'
5
6
  require_relative 'languages'
6
7
 
@@ -109,6 +110,46 @@ module Deliver
109
110
  valid_screenshots
110
111
  end
111
112
 
113
+ # Returns the list of valid app clip header images. When detecting invalid header images, this
114
+ # will cause an error. There may only be a max of one image per language and each image must be
115
+ # exactly 1800x1200.
116
+ #
117
+ # @param root [String] A directory path
118
+ # @param ignore_validation [String] Set false not to raise the error when
119
+ # finding invalid folder name @return [Array<Deliver::AppClipHeaderImage>]
120
+ # The list of AppClipHeaderImage that exists under given `root` directory
121
+ def self.load_app_clip_header_images(root, ignore_validation)
122
+ language_folders_list = language_folders(root, ignore_validation, true)
123
+
124
+ # Load images from all language folders (including default)
125
+ app_clip_header_images = language_folders_list.flat_map do |language_folder|
126
+ paths = language_folder.file_paths
127
+ paths.map { |path| AppClipHeaderImage.new(path, language_folder.language) }
128
+ end
129
+
130
+ # validate the header images are 1800x1200 in size
131
+ app_clip_header_images.each do |header_image|
132
+ size = FastImage.size(header_image.path)
133
+ if size.nil?
134
+ UI.user_error!("Unable to read app clip header image file: #{header_image.path}")
135
+ end
136
+ size = size.join('x')
137
+ unless size.eql?("1800x1200")
138
+ UI.user_error!("App clip header images must be exactly 1800x1200 in size. Offending image has size #{size}: '#{header_image.path}'")
139
+ end
140
+ end
141
+
142
+ # validate there is only one header image per language
143
+ # Filter out nil languages (e.g., from default folder) before validation
144
+ app_clip_header_images.map(&:language).compact.each do |language|
145
+ if app_clip_header_images.find_all { |header_image| header_image.language.eql?(language) }.length > 1
146
+ UI.user_error!("There can only be one app clip header image per language. The language #{language} has more than one image.")
147
+ end
148
+ end
149
+
150
+ app_clip_header_images
151
+ end
152
+
112
153
  # Returns the list of language folders
113
154
  #
114
155
  # @param roort [String] A directory path to get the list of language folders
@@ -127,6 +127,14 @@ module Deliver
127
127
  env_name: "DELIVER_SCREENSHOTS_PATH",
128
128
  description: "Path to the folder containing the screenshots",
129
129
  optional: true),
130
+ FastlaneCore::ConfigItem.new(key: :app_clip_header_images_path,
131
+ env_name: "DELIVER_APP_CLIP_HEADER_IMAGES_PATH",
132
+ description: "Path to the folder containing the app clip header images",
133
+ optional: true),
134
+ FastlaneCore::ConfigItem.new(key: :app_clip_default_experience_metadata_path,
135
+ env_name: "DELIVER_APP_CLIP_DEFAULT_EXPERIENCE_METADATA_PATH",
136
+ description: "Path to the folder containing the app clip default experience metadata",
137
+ optional: true),
130
138
 
131
139
  # app previews (videos)
132
140
  FastlaneCore::ConfigItem.new(key: :app_previews_path,
@@ -404,6 +412,10 @@ module Deliver
404
412
  description: "Metadata: A hash containing the review information",
405
413
  optional: true,
406
414
  type: Hash),
415
+ FastlaneCore::ConfigItem.new(key: :app_clip_review_information,
416
+ description: "Metadata: A hash containing the app clip review information",
417
+ optional: true,
418
+ type: Hash),
407
419
  FastlaneCore::ConfigItem.new(key: :app_review_attachment_file,
408
420
  env_name: "DELIVER_APP_REVIEW_ATTACHMENT_FILE",
409
421
  description: "Metadata: Path to the app review attachment file",
@@ -484,6 +496,17 @@ module Deliver
484
496
  optional: true,
485
497
  default_value: true),
486
498
 
499
+ # app clip default experience
500
+ FastlaneCore::ConfigItem.new(key: :app_clip_default_experience_subtitle,
501
+ env_name: "DELIVER_APP_CLIP_DEFAULT_EXPERIENCE_SUBTITLE",
502
+ description: "The localized subtitle for the default app clip experience",
503
+ optional: true,
504
+ type: Hash),
505
+ FastlaneCore::ConfigItem.new(key: :app_clip_default_experience_action,
506
+ env_name: "DELIVER_APP_CLIP_DEFAULT_EXPERIENCE_ACTION",
507
+ description: "Action for the default app clip experience (OPEN, VIEW, PLAY)",
508
+ optional: true),
509
+
487
510
  # internal
488
511
  FastlaneCore::ConfigItem.new(key: :app,
489
512
  short_option: "-p",
@@ -9,6 +9,8 @@ require_relative 'html_generator'
9
9
  require_relative 'submit_for_review'
10
10
  require_relative 'upload_price_tier'
11
11
  require_relative 'upload_metadata'
12
+ require_relative 'upload_app_clip_default_experience_metadata'
13
+ require_relative 'upload_app_clip_default_experience_header_images'
12
14
  require_relative 'upload_screenshots'
13
15
  require_relative 'sync_screenshots'
14
16
  require_relative 'sync_app_previews'
@@ -136,6 +138,12 @@ module Deliver
136
138
 
137
139
  # Upload all metadata, screenshots, pricing information, etc. to App Store Connect
138
140
  def upload_metadata
141
+ # App clip experience metadata upload must happen before the upload metadata step. The app
142
+ # clip app store review detail upload depends on there being a valid app clip default
143
+ # experience on the edit version.
144
+ UploadAppClipDefaultExperienceMetadata.new.upload_metadata(options)
145
+ UploadAppClipDefaultExperienceHeaderImages.new.find_and_upload(options)
146
+
139
147
  upload_metadata = UploadMetadata.new(options)
140
148
  upload_screenshots = UploadScreenshots.new
141
149