fastlane 2.219.0 → 2.220.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +86 -86
  3. data/bin/console +11 -0
  4. data/bin/match_file +60 -0
  5. data/deliver/lib/deliver/download_screenshots.rb +2 -1
  6. data/deliver/lib/deliver/generate_summary.rb +1 -1
  7. data/deliver/lib/deliver/options.rb +14 -0
  8. data/deliver/lib/deliver/runner.rb +4 -4
  9. data/deliver/lib/deliver/upload_metadata.rb +43 -28
  10. data/deliver/lib/deliver/upload_screenshots.rb +15 -8
  11. data/fastlane/lib/fastlane/actions/appetize.rb +4 -0
  12. data/fastlane/lib/fastlane/actions/docs/sync_code_signing.md +6 -2
  13. data/fastlane/lib/fastlane/actions/git_add.rb +17 -2
  14. data/fastlane/lib/fastlane/actions/mailgun.rb +30 -8
  15. data/fastlane/lib/fastlane/actions/onesignal.rb +14 -2
  16. data/fastlane/lib/fastlane/actions/update_project_provisioning.rb +2 -1
  17. data/fastlane/lib/fastlane/actions/upload_symbols_to_sentry.rb +4 -2
  18. data/fastlane/lib/fastlane/commands_generator.rb +9 -0
  19. data/fastlane/lib/fastlane/console.rb +24 -0
  20. data/fastlane/lib/fastlane/helper/sh_helper.rb +1 -1
  21. data/fastlane/lib/fastlane/plugins/plugin_fetcher.rb +2 -1
  22. data/fastlane/lib/fastlane/plugins/plugin_info_collector.rb +2 -1
  23. data/fastlane/lib/fastlane/plugins/plugin_manager.rb +2 -1
  24. data/fastlane/lib/fastlane/version.rb +2 -1
  25. data/fastlane/swift/Deliverfile.swift +1 -1
  26. data/fastlane/swift/DeliverfileProtocol.swift +9 -1
  27. data/fastlane/swift/Fastlane.swift +41 -8
  28. data/fastlane/swift/Gymfile.swift +1 -1
  29. data/fastlane/swift/GymfileProtocol.swift +1 -1
  30. data/fastlane/swift/LaneFileProtocol.swift +1 -1
  31. data/fastlane/swift/Matchfile.swift +1 -1
  32. data/fastlane/swift/MatchfileProtocol.swift +1 -1
  33. data/fastlane/swift/OptionalConfigValue.swift +2 -2
  34. data/fastlane/swift/Precheckfile.swift +1 -1
  35. data/fastlane/swift/PrecheckfileProtocol.swift +1 -1
  36. data/fastlane/swift/Scanfile.swift +1 -1
  37. data/fastlane/swift/ScanfileProtocol.swift +1 -1
  38. data/fastlane/swift/Screengrabfile.swift +1 -1
  39. data/fastlane/swift/ScreengrabfileProtocol.swift +1 -1
  40. data/fastlane/swift/Snapshotfile.swift +1 -1
  41. data/fastlane/swift/SnapshotfileProtocol.swift +3 -3
  42. data/fastlane/swift/formatting/Brewfile.lock.json +17 -17
  43. data/fastlane_core/lib/fastlane_core/cert_checker.rb +11 -8
  44. data/fastlane_core/lib/fastlane_core/device_manager.rb +1 -1
  45. data/fastlane_core/lib/fastlane_core/helper.rb +0 -15
  46. data/fastlane_core/lib/fastlane_core/print_table.rb +16 -0
  47. data/fastlane_core/lib/fastlane_core/project.rb +5 -0
  48. data/fastlane_core/lib/fastlane_core/ui/fastlane_runner.rb +0 -4
  49. data/fastlane_core/lib/fastlane_core/ui/help_formatter.rb +1 -5
  50. data/frameit/lib/frameit/device_types.rb +4 -0
  51. data/frameit/lib/frameit/editor.rb +20 -0
  52. data/gym/lib/gym/detect_values.rb +2 -0
  53. data/gym/lib/gym/module.rb +2 -2
  54. data/match/lib/assets/READMETemplate.md +3 -5
  55. data/match/lib/match/encryption/encryption.rb +154 -0
  56. data/match/lib/match/encryption/openssl.rb +7 -38
  57. data/match/lib/match/encryption.rb +1 -0
  58. data/match/lib/match/runner.rb +45 -6
  59. data/match/lib/match/storage/git_storage.rb +4 -3
  60. data/match/lib/match/storage/interface.rb +9 -5
  61. data/pilot/lib/pilot/build_manager.rb +5 -2
  62. data/pilot/lib/pilot/manager.rb +2 -2
  63. data/pilot/lib/pilot/options.rb +1 -1
  64. data/snapshot/lib/snapshot/options.rb +2 -2
  65. data/snapshot/lib/snapshot/setup.rb +1 -1
  66. data/spaceship/lib/spaceship/connect_api/api_client.rb +1 -1
  67. data/spaceship/lib/spaceship/connect_api/models/app_info.rb +17 -0
  68. data/spaceship/lib/spaceship/connect_api/models/app_store_version.rb +44 -9
  69. data/spaceship/lib/spaceship/connect_api/models/beta_tester.rb +30 -2
  70. data/spaceship/lib/spaceship/connect_api/models/certificate.rb +2 -2
  71. data/spaceship/lib/spaceship/connect_api/models/device.rb +11 -6
  72. data/spaceship/lib/spaceship/connect_api/models/profile.rb +8 -1
  73. data/spaceship/lib/spaceship/connect_api/token.rb +2 -1
  74. data/spaceship/lib/spaceship/connect_api.rb +5 -2
  75. data/spaceship/lib/spaceship/portal/certificate.rb +2 -2
  76. data/spaceship/lib/spaceship/portal/provisioning_profile.rb +8 -1
  77. data/trainer/lib/trainer/xcresult.rb +6 -10
  78. metadata +46 -29
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fc5ecf6d8cf5ad100811fa9a386cf6bdc02d8e4054663e2c3a59d94624a7cda8
4
- data.tar.gz: 4bf38a96eba5cf4cb1918155136ead760e2462e8b2bdbd19bf2f7f29afbb39a3
3
+ metadata.gz: eec1401cd6a8a8a9e9c48fed9969a6ab44348fa672c2b75464b3265000dab288
4
+ data.tar.gz: 1c7bc580641838525e4705a83633da89a38f225dfaea07ba9ee1ee2f54e8676c
5
5
  SHA512:
6
- metadata.gz: 67749a0ada8ac8654b5d3b42221e41562249a014435e9f0bf8354e441370b072e34a25e422d40c81266a1395969d56c8898e6e0492d7d17b82e2c98864d97791
7
- data.tar.gz: 7e9d404f597ad89a09df94ca1c51b4f1bf6a894493cf66c6efb69eefd93bce34e429407d80cdb289a2170b70f9619ef4f8f77af1065c78aa3ba6a6602540b034
6
+ metadata.gz: 3d88cbca7c40d2882d7442db21b0725b2da0e641f267f0c581cd2c7344a5e220a46cdd84eae861609d0ed9940226953cb6a03094d6b0019eaca578e7fb6872ae
7
+ data.tar.gz: 830456faecb0a07cfda4f48d7e5bb6ea0fa558553a43ae59f18a2ae702062d6202d31f2285dc4bea2310bceb890cfde6fc848ebcfeb0dbc71eb4911938a018e7
data/README.md CHANGED
@@ -35,38 +35,50 @@ If the above doesn't help, please [submit an issue](https://github.com/fastlane/
35
35
  <!-- This table is regenerated and resorted on each release -->
36
36
  <table id='team'>
37
37
  <tr>
38
+ <td id='iulian-onofrei'>
39
+ <a href='https://github.com/revolter'>
40
+ <img src='https://github.com/revolter.png' width='140px;'>
41
+ </a>
42
+ <h4 align='center'><a href='https://twitter.com/Revolt666'>Iulian Onofrei</a></h4>
43
+ </td>
38
44
  <td id='manu-wallner'>
39
45
  <a href='https://github.com/milch'>
40
46
  <img src='https://github.com/milch.png' width='140px;'>
41
47
  </a>
42
48
  <h4 align='center'><a href='https://twitter.com/acrooow'>Manu Wallner</a></h4>
43
49
  </td>
44
- <td id='joshua-liebowitz'>
45
- <a href='https://github.com/taquitos'>
46
- <img src='https://github.com/taquitos.png' width='140px;'>
47
- </a>
48
- <h4 align='center'><a href='https://twitter.com/taquitos'>Joshua Liebowitz</a></h4>
49
- </td>
50
- <td id='danielle-tomlinson'>
51
- <a href='https://github.com/endocrimes'>
52
- <img src='https://github.com/endocrimes.png' width='140px;'>
50
+ <td id='fumiya-nakamura'>
51
+ <a href='https://github.com/nafu'>
52
+ <img src='https://github.com/nafu.png' width='140px;'>
53
53
  </a>
54
- <h4 align='center'><a href='https://twitter.com/endocrimes'>Danielle Tomlinson</a></h4>
54
+ <h4 align='center'><a href='https://twitter.com/nafu003'>Fumiya Nakamura</a></h4>
55
55
  </td>
56
- <td id='satoshi-namai'>
57
- <a href='https://github.com/ainame'>
58
- <img src='https://github.com/ainame.png' width='140px;'>
56
+ <td id='helmut-januschka'>
57
+ <a href='https://github.com/hjanuschka'>
58
+ <img src='https://github.com/hjanuschka.png' width='140px;'>
59
59
  </a>
60
- <h4 align='center'><a href='https://twitter.com/ainame'>Satoshi Namai</a></h4>
60
+ <h4 align='center'><a href='https://twitter.com/hjanuschka'>Helmut Januschka</a></h4>
61
61
  </td>
62
- <td id='felix-krause'>
63
- <a href='https://github.com/KrauseFx'>
64
- <img src='https://github.com/KrauseFx.png' width='140px;'>
62
+ <td id='jorge-revuelta-h'>
63
+ <a href='https://github.com/minuscorp'>
64
+ <img src='https://github.com/minuscorp.png' width='140px;'>
65
65
  </a>
66
- <h4 align='center'><a href='https://twitter.com/KrauseFx'>Felix Krause</a></h4>
66
+ <h4 align='center'><a href='https://twitter.com/minuscorp'>Jorge Revuelta H</a></h4>
67
67
  </td>
68
68
  </tr>
69
69
  <tr>
70
+ <td id='jan-piotrowski'>
71
+ <a href='https://github.com/janpio'>
72
+ <img src='https://github.com/janpio.png' width='140px;'>
73
+ </a>
74
+ <h4 align='center'><a href='https://twitter.com/Sujan'>Jan Piotrowski</a></h4>
75
+ </td>
76
+ <td id='daniel-jankowski'>
77
+ <a href='https://github.com/mollyIV'>
78
+ <img src='https://github.com/mollyIV.png' width='140px;'>
79
+ </a>
80
+ <h4 align='center'><a href='https://twitter.com/mollyIV'>Daniel Jankowski</a></h4>
81
+ </td>
70
82
  <td id='łukasz-grabowski'>
71
83
  <a href='https://github.com/lucgrabowski'>
72
84
  <img src='https://github.com/lucgrabowski.png' width='140px;'>
@@ -79,18 +91,6 @@ If the above doesn't help, please [submit an issue](https://github.com/fastlane/
79
91
  </a>
80
92
  <h4 align='center'><a href='https://twitter.com/mgrebenets'>Maksym Grebenets</a></h4>
81
93
  </td>
82
- <td id='fumiya-nakamura'>
83
- <a href='https://github.com/nafu'>
84
- <img src='https://github.com/nafu.png' width='140px;'>
85
- </a>
86
- <h4 align='center'><a href='https://twitter.com/nafu003'>Fumiya Nakamura</a></h4>
87
- </td>
88
- <td id='jérôme-lacoste'>
89
- <a href='https://github.com/lacostej'>
90
- <img src='https://github.com/lacostej.png' width='140px;'>
91
- </a>
92
- <h4 align='center'><a href='https://twitter.com/lacostej'>Jérôme Lacoste</a></h4>
93
- </td>
94
94
  <td id='stefan-natchev'>
95
95
  <a href='https://github.com/snatchev'>
96
96
  <img src='https://github.com/snatchev.png' width='140px;'>
@@ -99,11 +99,11 @@ If the above doesn't help, please [submit an issue](https://github.com/fastlane/
99
99
  </td>
100
100
  </tr>
101
101
  <tr>
102
- <td id='helmut-januschka'>
103
- <a href='https://github.com/hjanuschka'>
104
- <img src='https://github.com/hjanuschka.png' width='140px;'>
102
+ <td id='josh-holtz'>
103
+ <a href='https://github.com/joshdholtz'>
104
+ <img src='https://github.com/joshdholtz.png' width='140px;'>
105
105
  </a>
106
- <h4 align='center'><a href='https://twitter.com/hjanuschka'>Helmut Januschka</a></h4>
106
+ <h4 align='center'><a href='https://twitter.com/joshdholtz'>Josh Holtz</a></h4>
107
107
  </td>
108
108
  <td id='manish-rathi'>
109
109
  <a href='https://github.com/crazymanish'>
@@ -111,75 +111,75 @@ If the above doesn't help, please [submit an issue](https://github.com/fastlane/
111
111
  </a>
112
112
  <h4 align='center'><a href='https://twitter.com/iammanishrathi'>Manish Rathi</a></h4>
113
113
  </td>
114
- <td id='max-ott'>
115
- <a href='https://github.com/max-ott'>
116
- <img src='https://github.com/max-ott.png' width='140px;'>
114
+ <td id='felix-krause'>
115
+ <a href='https://github.com/KrauseFx'>
116
+ <img src='https://github.com/KrauseFx.png' width='140px;'>
117
117
  </a>
118
- <h4 align='center'><a href='https://twitter.com/ott_max'>Max Ott</a></h4>
118
+ <h4 align='center'><a href='https://twitter.com/KrauseFx'>Felix Krause</a></h4>
119
119
  </td>
120
- <td id='jimmy-dee'>
121
- <a href='https://github.com/jdee'>
122
- <img src='https://github.com/jdee.png' width='140px;'>
120
+ <td id='kohki-miki'>
121
+ <a href='https://github.com/giginet'>
122
+ <img src='https://github.com/giginet.png' width='140px;'>
123
123
  </a>
124
- <h4 align='center'>Jimmy Dee</h4>
124
+ <h4 align='center'><a href='https://twitter.com/giginet'>Kohki Miki</a></h4>
125
125
  </td>
126
- <td id='roger-oba'>
127
- <a href='https://github.com/rogerluan'>
128
- <img src='https://github.com/rogerluan.png' width='140px;'>
126
+ <td id='joshua-liebowitz'>
127
+ <a href='https://github.com/taquitos'>
128
+ <img src='https://github.com/taquitos.png' width='140px;'>
129
129
  </a>
130
- <h4 align='center'><a href='https://twitter.com/rogerluan_'>Roger Oba</a></h4>
130
+ <h4 align='center'><a href='https://twitter.com/taquitos'>Joshua Liebowitz</a></h4>
131
131
  </td>
132
132
  </tr>
133
133
  <tr>
134
- <td id='iulian-onofrei'>
135
- <a href='https://github.com/revolter'>
136
- <img src='https://github.com/revolter.png' width='140px;'>
134
+ <td id='aaron-brager'>
135
+ <a href='https://github.com/getaaron'>
136
+ <img src='https://github.com/getaaron.png' width='140px;'>
137
137
  </a>
138
- <h4 align='center'><a href='https://twitter.com/Revolt666'>Iulian Onofrei</a></h4>
138
+ <h4 align='center'><a href='https://twitter.com/getaaron'>Aaron Brager</a></h4>
139
139
  </td>
140
- <td id='josh-holtz'>
141
- <a href='https://github.com/joshdholtz'>
142
- <img src='https://github.com/joshdholtz.png' width='140px;'>
140
+ <td id='roger-oba'>
141
+ <a href='https://github.com/rogerluan'>
142
+ <img src='https://github.com/rogerluan.png' width='140px;'>
143
143
  </a>
144
- <h4 align='center'><a href='https://twitter.com/joshdholtz'>Josh Holtz</a></h4>
144
+ <h4 align='center'><a href='https://twitter.com/rogerluan_'>Roger Oba</a></h4>
145
145
  </td>
146
- <td id='daniel-jankowski'>
147
- <a href='https://github.com/mollyIV'>
148
- <img src='https://github.com/mollyIV.png' width='140px;'>
146
+ <td id='luka-mirosevic'>
147
+ <a href='https://github.com/lmirosevic'>
148
+ <img src='https://github.com/lmirosevic.png' width='140px;'>
149
149
  </a>
150
- <h4 align='center'><a href='https://twitter.com/mollyIV'>Daniel Jankowski</a></h4>
150
+ <h4 align='center'><a href='https://twitter.com/lmirosevic'>Luka Mirosevic</a></h4>
151
151
  </td>
152
- <td id='andrew-mcburney'>
153
- <a href='https://github.com/armcburney'>
154
- <img src='https://github.com/armcburney.png' width='140px;'>
152
+ <td id='matthew-ellis'>
153
+ <a href='https://github.com/matthewellis'>
154
+ <img src='https://github.com/matthewellis.png' width='140px;'>
155
155
  </a>
156
- <h4 align='center'><a href='https://twitter.com/armcburney'>Andrew McBurney</a></h4>
156
+ <h4 align='center'><a href='https://twitter.com/mellis1995'>Matthew Ellis</a></h4>
157
157
  </td>
158
- <td id='jan-piotrowski'>
159
- <a href='https://github.com/janpio'>
160
- <img src='https://github.com/janpio.png' width='140px;'>
158
+ <td id='satoshi-namai'>
159
+ <a href='https://github.com/ainame'>
160
+ <img src='https://github.com/ainame.png' width='140px;'>
161
161
  </a>
162
- <h4 align='center'><a href='https://twitter.com/Sujan'>Jan Piotrowski</a></h4>
162
+ <h4 align='center'><a href='https://twitter.com/ainame'>Satoshi Namai</a></h4>
163
163
  </td>
164
164
  </tr>
165
165
  <tr>
166
- <td id='luka-mirosevic'>
167
- <a href='https://github.com/lmirosevic'>
168
- <img src='https://github.com/lmirosevic.png' width='140px;'>
166
+ <td id='jimmy-dee'>
167
+ <a href='https://github.com/jdee'>
168
+ <img src='https://github.com/jdee.png' width='140px;'>
169
169
  </a>
170
- <h4 align='center'><a href='https://twitter.com/lmirosevic'>Luka Mirosevic</a></h4>
170
+ <h4 align='center'>Jimmy Dee</h4>
171
171
  </td>
172
- <td id='kohki-miki'>
173
- <a href='https://github.com/giginet'>
174
- <img src='https://github.com/giginet.png' width='140px;'>
172
+ <td id='max-ott'>
173
+ <a href='https://github.com/max-ott'>
174
+ <img src='https://github.com/max-ott.png' width='140px;'>
175
175
  </a>
176
- <h4 align='center'><a href='https://twitter.com/giginet'>Kohki Miki</a></h4>
176
+ <h4 align='center'><a href='https://twitter.com/ott_max'>Max Ott</a></h4>
177
177
  </td>
178
- <td id='aaron-brager'>
179
- <a href='https://github.com/getaaron'>
180
- <img src='https://github.com/getaaron.png' width='140px;'>
178
+ <td id='jérôme-lacoste'>
179
+ <a href='https://github.com/lacostej'>
180
+ <img src='https://github.com/lacostej.png' width='140px;'>
181
181
  </a>
182
- <h4 align='center'><a href='https://twitter.com/getaaron'>Aaron Brager</a></h4>
182
+ <h4 align='center'><a href='https://twitter.com/lacostej'>Jérôme Lacoste</a></h4>
183
183
  </td>
184
184
  <td id='olivier-halligon'>
185
185
  <a href='https://github.com/AliSoftware'>
@@ -187,19 +187,19 @@ If the above doesn't help, please [submit an issue](https://github.com/fastlane/
187
187
  </a>
188
188
  <h4 align='center'><a href='https://twitter.com/aligatr'>Olivier Halligon</a></h4>
189
189
  </td>
190
- <td id='jorge-revuelta-h'>
191
- <a href='https://github.com/minuscorp'>
192
- <img src='https://github.com/minuscorp.png' width='140px;'>
190
+ <td id='danielle-tomlinson'>
191
+ <a href='https://github.com/endocrimes'>
192
+ <img src='https://github.com/endocrimes.png' width='140px;'>
193
193
  </a>
194
- <h4 align='center'><a href='https://twitter.com/minuscorp'>Jorge Revuelta H</a></h4>
194
+ <h4 align='center'><a href='https://twitter.com/endocrimes'>Danielle Tomlinson</a></h4>
195
195
  </td>
196
196
  </tr>
197
197
  <tr>
198
- <td id='matthew-ellis'>
199
- <a href='https://github.com/matthewellis'>
200
- <img src='https://github.com/matthewellis.png' width='140px;'>
198
+ <td id='andrew-mcburney'>
199
+ <a href='https://github.com/armcburney'>
200
+ <img src='https://github.com/armcburney.png' width='140px;'>
201
201
  </a>
202
- <h4 align='center'><a href='https://twitter.com/mellis1995'>Matthew Ellis</a></h4>
202
+ <h4 align='center'><a href='https://twitter.com/armcburney'>Andrew McBurney</a></h4>
203
203
  </td>
204
204
  </table>
205
205
 
data/bin/console ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "fastlane"
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ require "irb"
11
+ IRB.start(__FILE__)
data/bin/match_file ADDED
@@ -0,0 +1,60 @@
1
+ #!/usr/bin/env ruby
2
+ require 'match'
3
+
4
+ # CLI to encrypt/decrypt files using fastlane match encryption layer
5
+
6
+ def usage
7
+ puts("USAGE: [encrypt|decrypt] input_path [output_path]")
8
+ exit(-1)
9
+ end
10
+
11
+ if ARGV.count < 2 || ARGV.count > 3
12
+ usage
13
+ end
14
+
15
+ method_name = ARGV.shift
16
+ unless ['encrypt', 'decrypt'].include?(method_name)
17
+ usage
18
+ end
19
+
20
+ input_file = ARGV.shift
21
+
22
+ if ARGV.count > 0
23
+ output_file = ARGV.shift
24
+ else
25
+ output_file = input_file
26
+ end
27
+
28
+ def ask_password(msg)
29
+ ask(msg) do |q|
30
+ q.whitespace = :chomp
31
+ q.echo = "*"
32
+ end
33
+ end
34
+
35
+ def ask_password_twice
36
+ password = ask_password("Enter the password: ")
37
+ return "" if password.empty? || password == "\u0003" # CTRL-C char
38
+ other = ask_password("Enter the password again: ")
39
+ if other == password
40
+ return password
41
+ else
42
+ return nil
43
+ end
44
+ end
45
+
46
+ # read the password
47
+ password = nil
48
+ loop do
49
+ password = ask_password_twice
50
+ break unless password.nil?
51
+ end
52
+
53
+ exit if password.empty?
54
+
55
+ begin
56
+ Match::Encryption::MatchFileEncryption.new.send(method_name, file_path: input_file, password: password, output_path: output_file)
57
+ rescue => e
58
+ puts("ERROR #{method_name}ing. [#{e}]. Check your password")
59
+ usage
60
+ end
@@ -1,5 +1,6 @@
1
1
  require_relative 'module'
2
2
  require 'spaceship'
3
+ require 'open-uri'
3
4
 
4
5
  module Deliver
5
6
  class DownloadScreenshots
@@ -67,7 +68,7 @@ module Deliver
67
68
  end
68
69
 
69
70
  path = File.join(containing_folder, file_name)
70
- File.binwrite(path, FastlaneCore::Helper.open_uri(url).read)
71
+ File.binwrite(path, URI.open(url).read)
71
72
  end
72
73
  end
73
74
  end
@@ -6,7 +6,7 @@ module Deliver
6
6
  class GenerateSummary
7
7
  def run(options)
8
8
  screenshots = UploadScreenshots.new.collect_screenshots(options)
9
- UploadMetadata.new.load_from_filesystem(options)
9
+ UploadMetadata.new(options).load_from_filesystem
10
10
  HtmlGenerator.new.render(options, screenshots, '.')
11
11
  end
12
12
  end
@@ -162,6 +162,11 @@ module Deliver
162
162
  description: "Clear all previously uploaded screenshots before uploading the new ones",
163
163
  type: Boolean,
164
164
  default_value: false),
165
+ FastlaneCore::ConfigItem.new(key: :screenshot_processing_timeout,
166
+ env_name: "DELIVER_SCREENSHOT_PROCESSING_TIMEOUT",
167
+ description: "Timeout in seconds to wait before considering screenshot processing as failed, used to handle cases where uploads to the App Store are stuck in processing",
168
+ type: Integer,
169
+ default_value: 3600),
165
170
  FastlaneCore::ConfigItem.new(key: :sync_screenshots,
166
171
  env_name: "DELIVER_SYNC_SCREENSHOTS",
167
172
  description: "Sync screenshots with local ones. This is currently beta option so set true to 'FASTLANE_ENABLE_BETA_DELIVER_SYNC_SCREENSHOTS' environment variable as well",
@@ -182,6 +187,15 @@ module Deliver
182
187
  description: "Rejects the previously submitted build if it's in a state where it's possible",
183
188
  type: Boolean,
184
189
  default_value: false),
190
+ FastlaneCore::ConfigItem.new(key: :version_check_wait_retry_limit,
191
+ env_name: "DELIVER_VERSION_CHECK_WAIT_RETRY_LIMIT",
192
+ description: "After submitting a new version, App Store Connect takes some time to recognize the new version and we must wait until it's available before attempting to upload metadata for it. There is a mechanism that will check if it's available and retry with an exponential backoff if it's not available yet. " \
193
+ "This option specifies how many times we should retry before giving up. Setting this to a value below 5 is not recommended and will likely cause failures. Increase this parameter when Apple servers seem to be degraded or slow",
194
+ type: Integer,
195
+ default_value: 7,
196
+ verify_block: proc do |value|
197
+ UI.user_error!("'#{value}' needs to be greater than 0") if value <= 0
198
+ end),
185
199
 
186
200
  # release
187
201
  FastlaneCore::ConfigItem.new(key: :automatic_release,
@@ -135,21 +135,21 @@ module Deliver
135
135
 
136
136
  # Upload all metadata, screenshots, pricing information, etc. to App Store Connect
137
137
  def upload_metadata
138
- upload_metadata = UploadMetadata.new
138
+ upload_metadata = UploadMetadata.new(options)
139
139
  upload_screenshots = UploadScreenshots.new
140
140
 
141
141
  # First, collect all the things for the HTML Report
142
142
  screenshots = upload_screenshots.collect_screenshots(options)
143
- upload_metadata.load_from_filesystem(options)
143
+ upload_metadata.load_from_filesystem
144
144
 
145
145
  # Assign "default" values to all languages
146
- upload_metadata.assign_defaults(options)
146
+ upload_metadata.assign_defaults
147
147
 
148
148
  # Validate
149
149
  validate_html(screenshots)
150
150
 
151
151
  # Commit
152
- upload_metadata.upload(options)
152
+ upload_metadata.upload
153
153
 
154
154
  if options[:sync_screenshots]
155
155
  sync_screenshots = SyncScreenshots.new(app: Deliver.cache[:app], platform: Spaceship::ConnectAPI::Platform.map(options[:platform]))
@@ -78,19 +78,25 @@ module Deliver
78
78
 
79
79
  require_relative 'loader'
80
80
 
81
+ attr_accessor :options
82
+
83
+ def initialize(options)
84
+ self.options = options
85
+ end
86
+
81
87
  # Make sure to call `load_from_filesystem` before calling upload
82
- def upload(options)
88
+ def upload
83
89
  return if options[:skip_metadata]
84
90
 
85
91
  app = Deliver.cache[:app]
86
92
 
87
93
  platform = Spaceship::ConnectAPI::Platform.map(options[:platform])
88
94
 
89
- enabled_languages = detect_languages(options)
95
+ enabled_languages = detect_languages
90
96
 
91
- app_store_version_localizations = verify_available_version_languages!(options, app, enabled_languages) unless options[:edit_live]
97
+ app_store_version_localizations = verify_available_version_languages!(app, enabled_languages) unless options[:edit_live]
92
98
  app_info = fetch_edit_app_info(app)
93
- app_info_localizations = verify_available_info_languages!(options, app, app_info, enabled_languages) unless options[:edit_live] || !updating_localized_app_info?(options, app, app_info)
99
+ app_info_localizations = verify_available_info_languages!(app, app_info, enabled_languages) unless options[:edit_live] || !updating_localized_app_info?(app, app_info)
94
100
 
95
101
  if options[:edit_live]
96
102
  # not all values are editable when using live_version
@@ -342,9 +348,9 @@ module Deliver
342
348
  end
343
349
  end
344
350
 
345
- set_review_information(version, options)
346
- set_review_attachment_file(version, options)
347
- set_app_rating(app_info, options)
351
+ review_information(version)
352
+ review_attachment_file(version)
353
+ app_rating(app_info)
348
354
  end
349
355
 
350
356
  # rubocop:enable Metrics/PerceivedComplexity
@@ -360,12 +366,12 @@ module Deliver
360
366
  end
361
367
 
362
368
  # If the user is using the 'default' language, then assign values where they are needed
363
- def assign_defaults(options)
369
+ def assign_defaults
364
370
  # Normalizes languages keys from symbols to strings
365
- normalize_language_keys(options)
371
+ normalize_language_keys
366
372
 
367
373
  # Build a complete list of the required languages
368
- enabled_languages = detect_languages(options)
374
+ enabled_languages = detect_languages
369
375
 
370
376
  # Get all languages used in existing settings
371
377
  (LOCALISED_VERSION_VALUES.keys + LOCALISED_APP_VALUES.keys).each do |key|
@@ -402,7 +408,7 @@ module Deliver
402
408
  end
403
409
  end
404
410
 
405
- def detect_languages(options)
411
+ def detect_languages
406
412
  # Build a complete list of the required languages
407
413
  enabled_languages = options[:languages] || []
408
414
 
@@ -427,40 +433,49 @@ module Deliver
427
433
  .uniq
428
434
  end
429
435
 
430
- def fetch_edit_app_store_version(app, platform, wait_time: 10)
431
- retry_if_nil("Cannot find edit app store version", wait_time: wait_time) do
436
+ def fetch_edit_app_store_version(app, platform)
437
+ retry_if_nil("Cannot find edit app store version") do
432
438
  app.get_edit_app_store_version(platform: platform)
433
439
  end
434
440
  end
435
441
 
436
- def fetch_edit_app_info(app, wait_time: 10)
437
- retry_if_nil("Cannot find edit app info", wait_time: wait_time) do
442
+ def fetch_edit_app_info(app)
443
+ retry_if_nil("Cannot find edit app info") do
438
444
  app.fetch_edit_app_info
439
445
  end
440
446
  end
441
447
 
442
- def fetch_live_app_info(app, wait_time: 10)
443
- retry_if_nil("Cannot find live app info", wait_time: wait_time) do
448
+ def fetch_live_app_info(app)
449
+ retry_if_nil("Cannot find live app info") do
444
450
  app.fetch_live_app_info
445
451
  end
446
452
  end
447
453
 
448
- def retry_if_nil(message, tries: 5, wait_time: 10)
454
+ # Retries a block of code if the return value is nil, with an exponential backoff.
455
+ def retry_if_nil(message)
456
+ tries = options[:version_check_wait_retry_limit]
457
+ wait_time = 10
449
458
  loop do
450
459
  tries -= 1
451
460
 
452
461
  value = yield
453
462
  return value if value
454
463
 
455
- UI.message("#{message}... Retrying after #{wait_time} seconds (remaining: #{tries})")
456
- sleep(wait_time)
464
+ # Calculate sleep time to be the lesser of the exponential backoff or 5 minutes.
465
+ # This prevents problems with CI's console output timeouts (of usually 10 minutes), and also
466
+ # speeds up the retry time for the user, as waiting longer than 5 minutes is a too long wait for a retry.
467
+ sleep_time = [wait_time * 2, 5 * 60].min
468
+ UI.message("#{message}... Retrying after #{sleep_time} seconds (remaining: #{tries})")
469
+ Kernel.sleep(sleep_time)
457
470
 
458
471
  return nil if tries.zero?
472
+
473
+ wait_time *= 2 # Double the wait time for the next iteration
459
474
  end
460
475
  end
461
476
 
462
477
  # Checking if the metadata to update includes localised App Info
463
- def updating_localized_app_info?(options, app, app_info)
478
+ def updating_localized_app_info?(app, app_info)
464
479
  app_info ||= fetch_live_app_info(app)
465
480
  unless app_info
466
481
  UI.important("Can't find edit or live App info. Skipping upload.")
@@ -499,7 +514,7 @@ module Deliver
499
514
  end
500
515
 
501
516
  # Finding languages to enable
502
- def verify_available_info_languages!(options, app, app_info, languages)
517
+ def verify_available_info_languages!(app, app_info, languages)
503
518
  unless app_info
504
519
  UI.user_error!("Cannot update languages - could not find an editable 'App Info'. Verify that your app is in one of the editable states in App Store Connect")
505
520
  return
@@ -531,7 +546,7 @@ module Deliver
531
546
  end
532
547
 
533
548
  # Finding languages to enable
534
- def verify_available_version_languages!(options, app, languages)
549
+ def verify_available_version_languages!(app, languages)
535
550
  platform = Spaceship::ConnectAPI::Platform.map(options[:platform])
536
551
  version = fetch_edit_app_store_version(app, platform)
537
552
 
@@ -566,7 +581,7 @@ module Deliver
566
581
  end
567
582
 
568
583
  # Loads the metadata files and stores them into the options object
569
- def load_from_filesystem(options)
584
+ def load_from_filesystem
570
585
  return if options[:skip_metadata]
571
586
 
572
587
  # Load localised data
@@ -623,7 +638,7 @@ module Deliver
623
638
  private
624
639
 
625
640
  # Normalizes languages keys from symbols to strings
626
- def normalize_language_keys(options)
641
+ def normalize_language_keys
627
642
  (LOCALISED_VERSION_VALUES.keys + LOCALISED_APP_VALUES.keys).each do |key|
628
643
  current = options[key]
629
644
  next unless current && current.kind_of?(Hash)
@@ -636,7 +651,7 @@ module Deliver
636
651
  options
637
652
  end
638
653
 
639
- def set_review_information(version, options)
654
+ def review_information(version)
640
655
  info = options[:app_review_information]
641
656
  return if info.nil? || info.empty?
642
657
 
@@ -669,7 +684,7 @@ module Deliver
669
684
  end
670
685
  end
671
686
 
672
- def set_review_attachment_file(version, options)
687
+ def review_attachment_file(version)
673
688
  app_store_review_detail = version.fetch_app_store_review_detail
674
689
  app_store_review_attachments = app_store_review_detail.app_store_review_attachments || []
675
690
 
@@ -687,7 +702,7 @@ module Deliver
687
702
  end
688
703
  end
689
704
 
690
- def set_app_rating(app_info, options)
705
+ def app_rating(app_info)
691
706
  return unless options[:app_rating_config_path]
692
707
 
693
708
  require 'json'