fastlane 2.169.0 → 2.174.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (123) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +76 -76
  3. data/deliver/lib/deliver/app_screenshot.rb +5 -7
  4. data/deliver/lib/deliver/app_screenshot_validator.rb +108 -0
  5. data/deliver/lib/deliver/commands_generator.rb +1 -1
  6. data/deliver/lib/deliver/loader.rb +13 -29
  7. data/deliver/lib/deliver/setup.rb +8 -3
  8. data/deliver/lib/deliver/upload_metadata.rb +5 -3
  9. data/fastlane/lib/fastlane/actions/add_git_tag.rb +12 -3
  10. data/fastlane/lib/fastlane/actions/app_store_connect_api_key.rb +1 -0
  11. data/fastlane/lib/fastlane/actions/appetize.rb +13 -1
  12. data/fastlane/lib/fastlane/actions/artifactory.rb +36 -3
  13. data/fastlane/lib/fastlane/actions/build_and_upload_to_appetize.rb +10 -2
  14. data/fastlane/lib/fastlane/actions/build_app.rb +3 -1
  15. data/fastlane/lib/fastlane/actions/carthage.rb +22 -0
  16. data/fastlane/lib/fastlane/actions/cocoapods.rb +15 -1
  17. data/fastlane/lib/fastlane/actions/create_pull_request.rb +16 -1
  18. data/fastlane/lib/fastlane/actions/create_xcframework.rb +118 -0
  19. data/fastlane/lib/fastlane/actions/docs/sync_code_signing.md +1 -1
  20. data/fastlane/lib/fastlane/actions/docs/upload_to_app_store.md.erb +4 -0
  21. data/fastlane/lib/fastlane/actions/docs/upload_to_testflight.md +5 -1
  22. data/fastlane/lib/fastlane/actions/download_app_privacy_details_from_app_store.rb +142 -0
  23. data/fastlane/lib/fastlane/actions/download_dsyms.rb +0 -1
  24. data/fastlane/lib/fastlane/actions/git_commit.rb +6 -2
  25. data/fastlane/lib/fastlane/actions/github_api.rb +14 -3
  26. data/fastlane/lib/fastlane/actions/nexus_upload.rb +1 -0
  27. data/fastlane/lib/fastlane/actions/onesignal.rb +13 -3
  28. data/fastlane/lib/fastlane/actions/pod_push.rb +9 -0
  29. data/fastlane/lib/fastlane/actions/push_to_git_remote.rb +9 -1
  30. data/fastlane/lib/fastlane/actions/register_device.rb +1 -1
  31. data/fastlane/lib/fastlane/actions/register_devices.rb +2 -1
  32. data/fastlane/lib/fastlane/actions/set_github_release.rb +21 -8
  33. data/fastlane/lib/fastlane/actions/slack.rb +4 -5
  34. data/fastlane/lib/fastlane/actions/spm.rb +2 -2
  35. data/fastlane/lib/fastlane/actions/swiftlint.rb +4 -4
  36. data/fastlane/lib/fastlane/actions/upload_app_privacy_details_to_app_store.rb +291 -0
  37. data/fastlane/lib/fastlane/cli_tools_distributor.rb +3 -0
  38. data/fastlane/lib/fastlane/plugins/template/.rubocop.yml +1 -1
  39. data/fastlane/lib/fastlane/swift_fastlane_api_generator.rb +3 -0
  40. data/fastlane/lib/fastlane/version.rb +1 -1
  41. data/fastlane/swift/Actions.swift +1 -1
  42. data/fastlane/swift/Appfile.swift +1 -1
  43. data/fastlane/swift/ArgumentProcessor.swift +1 -1
  44. data/fastlane/swift/ControlCommand.swift +1 -1
  45. data/fastlane/swift/Deliverfile.swift +2 -2
  46. data/fastlane/swift/DeliverfileProtocol.swift +2 -2
  47. data/fastlane/swift/Fastlane.swift +253 -37
  48. data/fastlane/swift/Gymfile.swift +2 -2
  49. data/fastlane/swift/GymfileProtocol.swift +11 -3
  50. data/fastlane/swift/LaneFileProtocol.swift +1 -1
  51. data/fastlane/swift/MainProcess.swift +1 -1
  52. data/fastlane/swift/Matchfile.swift +2 -2
  53. data/fastlane/swift/MatchfileProtocol.swift +2 -2
  54. data/fastlane/swift/Plugins.swift +1 -1
  55. data/fastlane/swift/Precheckfile.swift +2 -2
  56. data/fastlane/swift/PrecheckfileProtocol.swift +6 -2
  57. data/fastlane/swift/RubyCommand.swift +1 -1
  58. data/fastlane/swift/RubyCommandable.swift +1 -1
  59. data/fastlane/swift/Runner.swift +2 -2
  60. data/fastlane/swift/RunnerArgument.swift +1 -1
  61. data/fastlane/swift/Scanfile.swift +2 -2
  62. data/fastlane/swift/ScanfileProtocol.swift +14 -2
  63. data/fastlane/swift/Screengrabfile.swift +2 -2
  64. data/fastlane/swift/ScreengrabfileProtocol.swift +2 -2
  65. data/fastlane/swift/Snapshotfile.swift +2 -2
  66. data/fastlane/swift/SnapshotfileProtocol.swift +15 -3
  67. data/fastlane/swift/SocketClient.swift +1 -1
  68. data/fastlane/swift/SocketClientDelegateProtocol.swift +1 -1
  69. data/fastlane/swift/SocketResponse.swift +1 -1
  70. data/fastlane/swift/formatting/Brewfile.lock.json +18 -14
  71. data/fastlane/swift/main.swift +1 -1
  72. data/fastlane_core/lib/fastlane_core/configuration/configuration.rb +7 -1
  73. data/fastlane_core/lib/fastlane_core/helper.rb +2 -2
  74. data/fastlane_core/lib/fastlane_core/ipa_file_analyser.rb +41 -16
  75. data/fastlane_core/lib/fastlane_core/itunes_transporter.rb +3 -4
  76. data/fastlane_core/lib/fastlane_core/project.rb +41 -14
  77. data/frameit/lib/frameit/device_types.rb +7 -1
  78. data/gym/lib/gym/error_handler.rb +8 -0
  79. data/gym/lib/gym/generators/build_command_generator.rb +3 -1
  80. data/gym/lib/gym/generators/package_command_generator_xcode7.rb +2 -2
  81. data/gym/lib/gym/options.rb +12 -2
  82. data/match/lib/match/encryption/openssl.rb +4 -2
  83. data/match/lib/match/runner.rb +1 -1
  84. data/match/lib/match/storage/git_storage.rb +14 -10
  85. data/precheck/lib/precheck/options.rb +6 -1
  86. data/precheck/lib/precheck/rule_processor.rb +1 -1
  87. data/precheck/lib/precheck/runner.rb +1 -1
  88. data/scan/lib/scan/options.rb +15 -0
  89. data/scan/lib/scan/runner.rb +6 -1
  90. data/scan/lib/scan/slack_poster.rb +4 -1
  91. data/scan/lib/scan/test_command_generator.rb +3 -1
  92. data/screengrab/lib/screengrab/runner.rb +2 -0
  93. data/sigh/lib/sigh/runner.rb +1 -1
  94. data/snapshot/lib/assets/SnapshotHelper.swift +1 -1
  95. data/snapshot/lib/snapshot/options.rb +17 -2
  96. data/snapshot/lib/snapshot/update.rb +1 -1
  97. data/spaceship/lib/spaceship/client.rb +14 -1
  98. data/spaceship/lib/spaceship/connect_api.rb +6 -0
  99. data/spaceship/lib/spaceship/connect_api/api_client.rb +17 -2
  100. data/spaceship/lib/spaceship/connect_api/models/app.rb +6 -0
  101. data/spaceship/lib/spaceship/connect_api/models/app_data_usage.rb +59 -0
  102. data/spaceship/lib/spaceship/connect_api/models/app_data_usage_category.rb +65 -0
  103. data/spaceship/lib/spaceship/connect_api/models/app_data_usage_data_protection.rb +27 -0
  104. data/spaceship/lib/spaceship/connect_api/models/app_data_usage_grouping.rb +18 -0
  105. data/spaceship/lib/spaceship/connect_api/models/app_data_usage_purposes.rb +37 -0
  106. data/spaceship/lib/spaceship/connect_api/models/app_data_usages_publish_state.rb +36 -0
  107. data/spaceship/lib/spaceship/connect_api/models/app_store_version.rb +7 -1
  108. data/spaceship/lib/spaceship/connect_api/models/beta_group.rb +9 -0
  109. data/spaceship/lib/spaceship/connect_api/models/bundle_id.rb +24 -0
  110. data/spaceship/lib/spaceship/connect_api/models/bundle_id_capability.rb +26 -4
  111. data/spaceship/lib/spaceship/connect_api/models/device.rb +30 -0
  112. data/spaceship/lib/spaceship/connect_api/provisioning/provisioning.rb +53 -0
  113. data/spaceship/lib/spaceship/connect_api/response.rb +3 -1
  114. data/spaceship/lib/spaceship/connect_api/testflight/testflight.rb +12 -0
  115. data/spaceship/lib/spaceship/connect_api/tunes/tunes.rb +103 -0
  116. data/spaceship/lib/spaceship/two_step_or_factor_client.rb +1 -0
  117. data/spaceship/lib/spaceship/upgrade_2fa_later_client.rb +91 -0
  118. metadata +45 -25
  119. data/cert/lib/cert/.options.rb.swp +0 -0
  120. data/cert/lib/cert/.runner.rb.swp +0 -0
  121. data/fastlane/lib/fastlane/actions/.download_dsyms.rb.swp +0 -0
  122. data/match/lib/match/.options.rb.swp +0 -0
  123. data/sigh/lib/sigh/.options.rb.swp +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 89942043b1528ca3c3eff8b253e5c13a8fe910178b1670a553197f27260bb7d5
4
- data.tar.gz: 476dffe7ef2b50121441191673e20041e4c91cdb8eecc5e1928a9f02930538b0
3
+ metadata.gz: 4661f027a61fae05c35c80827aedd5435cbf631579a1232061edd76bb9c8df61
4
+ data.tar.gz: 88f4f9a19d0136ba3acb5cc2dffe65308bb6437eefc56ae39692b78590a385f1
5
5
  SHA512:
6
- metadata.gz: 26f4595813c6d3bdea582beabb32f4824b170dc660cf576d01aa1e6c696781e7538c6740bf09246f492ed06ac05a15db5eb0de88e21ccc07ed00e24b373c9380
7
- data.tar.gz: e711d070232cecbcb7749c47c0fa6ac72e19b137753856c39de6739a55fd6159d4943575f784eb06070e12ba2d02ba5aea478481b48be8b9561a360e0756fa27
6
+ metadata.gz: 84f565e3caea07cb1dbad2c4dbe47dec93414cc5fb104b989087ad79744fb3c41b8d31e369b39698dc89aa2688b74fc1ddf6617a115de6e4f5381b11ac7d410b
7
+ data.tar.gz: 693492a716a243e76e4a4a02452a4cfc83b0ee9d09092d7b8442151ab2b2370eabddbadddcd92d7e6b11a733f0bd7fe92f2bbfd7077c109abb1ff42602fe661d
data/README.md CHANGED
@@ -34,49 +34,43 @@ 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='josh-holtz'>
38
- <a href='https://github.com/joshdholtz'>
39
- <img src='https://github.com/joshdholtz.png?size=140'>
37
+ <td id='aaron-brager'>
38
+ <a href='https://github.com/getaaron'>
39
+ <img src='https://github.com/getaaron.png?size=140'>
40
40
  </a>
41
- <h4 align='center'><a href='https://twitter.com/joshdholtz'>Josh Holtz</a></h4>
41
+ <h4 align='center'><a href='https://twitter.com/getaaron'>Aaron Brager</a></h4>
42
42
  </td>
43
- <td id='maksym-grebenets'>
44
- <a href='https://github.com/mgrebenets'>
45
- <img src='https://github.com/mgrebenets.png?size=140'>
43
+ <td id='jérôme-lacoste'>
44
+ <a href='https://github.com/lacostej'>
45
+ <img src='https://github.com/lacostej.png?size=140'>
46
46
  </a>
47
- <h4 align='center'><a href='https://twitter.com/mgrebenets'>Maksym Grebenets</a></h4>
47
+ <h4 align='center'><a href='https://twitter.com/lacostej'>Jérôme Lacoste</a></h4>
48
48
  </td>
49
- <td id='matthew-ellis'>
50
- <a href='https://github.com/matthewellis'>
51
- <img src='https://github.com/matthewellis.png?size=140'>
49
+ <td id='danielle-tomlinson'>
50
+ <a href='https://github.com/endocrimes'>
51
+ <img src='https://github.com/endocrimes.png?size=140'>
52
52
  </a>
53
- <h4 align='center'><a href='https://twitter.com/mellis1995'>Matthew Ellis</a></h4>
53
+ <h4 align='center'><a href='https://twitter.com/endocrimes'>Danielle Tomlinson</a></h4>
54
54
  </td>
55
- <td id='aaron-brager'>
56
- <a href='https://github.com/getaaron'>
57
- <img src='https://github.com/getaaron.png?size=140'>
55
+ <td id='iulian-onofrei'>
56
+ <a href='https://github.com/revolter'>
57
+ <img src='https://github.com/revolter.png?size=140'>
58
58
  </a>
59
- <h4 align='center'><a href='https://twitter.com/getaaron'>Aaron Brager</a></h4>
59
+ <h4 align='center'><a href='https://twitter.com/Revolt666'>Iulian Onofrei</a></h4>
60
60
  </td>
61
- <td id='jorge-revuelta-h'>
62
- <a href='https://github.com/minuscorp'>
63
- <img src='https://github.com/minuscorp.png?size=140'>
61
+ <td id='olivier-halligon'>
62
+ <a href='https://github.com/AliSoftware'>
63
+ <img src='https://github.com/AliSoftware.png?size=140'>
64
64
  </a>
65
- <h4 align='center'><a href='https://twitter.com/minuscorp'>Jorge Revuelta H</a></h4>
65
+ <h4 align='center'><a href='https://twitter.com/aligatr'>Olivier Halligon</a></h4>
66
66
  </td>
67
67
  </tr>
68
68
  <tr>
69
- <td id='jan-piotrowski'>
70
- <a href='https://github.com/janpio'>
71
- <img src='https://github.com/janpio.png?size=140'>
72
- </a>
73
- <h4 align='center'><a href='https://twitter.com/Sujan'>Jan Piotrowski</a></h4>
74
- </td>
75
- <td id='kohki-miki'>
76
- <a href='https://github.com/giginet'>
77
- <img src='https://github.com/giginet.png?size=140'>
69
+ <td id='luka-mirosevic'>
70
+ <a href='https://github.com/lmirosevic'>
71
+ <img src='https://github.com/lmirosevic.png?size=140'>
78
72
  </a>
79
- <h4 align='center'><a href='https://twitter.com/giginet'>Kohki Miki</a></h4>
73
+ <h4 align='center'><a href='https://twitter.com/lmirosevic'>Luka Mirosevic</a></h4>
80
74
  </td>
81
75
  <td id='max-ott'>
82
76
  <a href='https://github.com/max-ott'>
@@ -84,18 +78,24 @@ If the above doesn't help, please [submit an issue](https://github.com/fastlane/
84
78
  </a>
85
79
  <h4 align='center'><a href='https://twitter.com/ott_max'>Max Ott</a></h4>
86
80
  </td>
87
- <td id='iulian-onofrei'>
88
- <a href='https://github.com/revolter'>
89
- <img src='https://github.com/revolter.png?size=140'>
90
- </a>
91
- <h4 align='center'><a href='https://twitter.com/Revolt666'>Iulian Onofrei</a></h4>
92
- </td>
93
81
  <td id='fumiya-nakamura'>
94
82
  <a href='https://github.com/nafu'>
95
83
  <img src='https://github.com/nafu.png?size=140'>
96
84
  </a>
97
85
  <h4 align='center'><a href='https://twitter.com/nafu003'>Fumiya Nakamura</a></h4>
98
86
  </td>
87
+ <td id='maksym-grebenets'>
88
+ <a href='https://github.com/mgrebenets'>
89
+ <img src='https://github.com/mgrebenets.png?size=140'>
90
+ </a>
91
+ <h4 align='center'><a href='https://twitter.com/mgrebenets'>Maksym Grebenets</a></h4>
92
+ </td>
93
+ <td id='stefan-natchev'>
94
+ <a href='https://github.com/snatchev'>
95
+ <img src='https://github.com/snatchev.png?size=140'>
96
+ </a>
97
+ <h4 align='center'><a href='https://twitter.com/snatchev'>Stefan Natchev</a></h4>
98
+ </td>
99
99
  </tr>
100
100
  <tr>
101
101
  <td id='felix-krause'>
@@ -104,75 +104,75 @@ If the above doesn't help, please [submit an issue](https://github.com/fastlane/
104
104
  </a>
105
105
  <h4 align='center'><a href='https://twitter.com/KrauseFx'>Felix Krause</a></h4>
106
106
  </td>
107
+ <td id='jimmy-dee'>
108
+ <a href='https://github.com/jdee'>
109
+ <img src='https://github.com/jdee.png?size=140'>
110
+ </a>
111
+ <h4 align='center'>Jimmy Dee</h4>
112
+ </td>
107
113
  <td id='daniel-jankowski'>
108
114
  <a href='https://github.com/mollyIV'>
109
115
  <img src='https://github.com/mollyIV.png?size=140'>
110
116
  </a>
111
117
  <h4 align='center'><a href='https://twitter.com/mollyIV'>Daniel Jankowski</a></h4>
112
118
  </td>
113
- <td id='manu-wallner'>
114
- <a href='https://github.com/milch'>
115
- <img src='https://github.com/milch.png?size=140'>
116
- </a>
117
- <h4 align='center'><a href='https://twitter.com/acrooow'>Manu Wallner</a></h4>
118
- </td>
119
- <td id='helmut-januschka'>
120
- <a href='https://github.com/hjanuschka'>
121
- <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'>
122
122
  </a>
123
- <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>
124
124
  </td>
125
- <td id='danielle-tomlinson'>
126
- <a href='https://github.com/endocrimes'>
127
- <img src='https://github.com/endocrimes.png?size=140'>
125
+ <td id='jan-piotrowski'>
126
+ <a href='https://github.com/janpio'>
127
+ <img src='https://github.com/janpio.png?size=140'>
128
128
  </a>
129
- <h4 align='center'><a href='https://twitter.com/endocrimes'>Danielle Tomlinson</a></h4>
129
+ <h4 align='center'><a href='https://twitter.com/Sujan'>Jan Piotrowski</a></h4>
130
130
  </td>
131
131
  </tr>
132
132
  <tr>
133
+ <td id='jorge-revuelta-h'>
134
+ <a href='https://github.com/minuscorp'>
135
+ <img src='https://github.com/minuscorp.png?size=140'>
136
+ </a>
137
+ <h4 align='center'><a href='https://twitter.com/minuscorp'>Jorge Revuelta H</a></h4>
138
+ </td>
133
139
  <td id='andrew-mcburney'>
134
140
  <a href='https://github.com/armcburney'>
135
141
  <img src='https://github.com/armcburney.png?size=140'>
136
142
  </a>
137
143
  <h4 align='center'><a href='https://twitter.com/armcburney'>Andrew McBurney</a></h4>
138
144
  </td>
139
- <td id='jérôme-lacoste'>
140
- <a href='https://github.com/lacostej'>
141
- <img src='https://github.com/lacostej.png?size=140'>
142
- </a>
143
- <h4 align='center'><a href='https://twitter.com/lacostej'>Jérôme Lacoste</a></h4>
144
- </td>
145
- <td id='stefan-natchev'>
146
- <a href='https://github.com/snatchev'>
147
- <img src='https://github.com/snatchev.png?size=140'>
145
+ <td id='manu-wallner'>
146
+ <a href='https://github.com/milch'>
147
+ <img src='https://github.com/milch.png?size=140'>
148
148
  </a>
149
- <h4 align='center'><a href='https://twitter.com/snatchev'>Stefan Natchev</a></h4>
149
+ <h4 align='center'><a href='https://twitter.com/acrooow'>Manu Wallner</a></h4>
150
150
  </td>
151
- <td id='joshua-liebowitz'>
152
- <a href='https://github.com/taquitos'>
153
- <img src='https://github.com/taquitos.png?size=140'>
151
+ <td id='kohki-miki'>
152
+ <a href='https://github.com/giginet'>
153
+ <img src='https://github.com/giginet.png?size=140'>
154
154
  </a>
155
- <h4 align='center'><a href='https://twitter.com/taquitos'>Joshua Liebowitz</a></h4>
155
+ <h4 align='center'><a href='https://twitter.com/giginet'>Kohki Miki</a></h4>
156
156
  </td>
157
- <td id='jimmy-dee'>
158
- <a href='https://github.com/jdee'>
159
- <img src='https://github.com/jdee.png?size=140'>
157
+ <td id='helmut-januschka'>
158
+ <a href='https://github.com/hjanuschka'>
159
+ <img src='https://github.com/hjanuschka.png?size=140'>
160
160
  </a>
161
- <h4 align='center'>Jimmy Dee</h4>
161
+ <h4 align='center'><a href='https://twitter.com/hjanuschka'>Helmut Januschka</a></h4>
162
162
  </td>
163
163
  </tr>
164
164
  <tr>
165
- <td id='olivier-halligon'>
166
- <a href='https://github.com/AliSoftware'>
167
- <img src='https://github.com/AliSoftware.png?size=140'>
165
+ <td id='matthew-ellis'>
166
+ <a href='https://github.com/matthewellis'>
167
+ <img src='https://github.com/matthewellis.png?size=140'>
168
168
  </a>
169
- <h4 align='center'><a href='https://twitter.com/aligatr'>Olivier Halligon</a></h4>
169
+ <h4 align='center'><a href='https://twitter.com/mellis1995'>Matthew Ellis</a></h4>
170
170
  </td>
171
- <td id='luka-mirosevic'>
172
- <a href='https://github.com/lmirosevic'>
173
- <img src='https://github.com/lmirosevic.png?size=140'>
171
+ <td id='joshua-liebowitz'>
172
+ <a href='https://github.com/taquitos'>
173
+ <img src='https://github.com/taquitos.png?size=140'>
174
174
  </a>
175
- <h4 align='center'><a href='https://twitter.com/lmirosevic'>Luka Mirosevic</a></h4>
175
+ <h4 align='center'><a href='https://twitter.com/taquitos'>Joshua Liebowitz</a></h4>
176
176
  </td>
177
177
  </table>
178
178
 
@@ -82,15 +82,12 @@ module Deliver
82
82
  # @param path (String) path to the screenshot file
83
83
  # @param language (String) Language of this screenshot (e.g. English)
84
84
  # @param screen_size (Deliver::AppScreenshot::ScreenSize) the screen size, which
85
- # will automatically be calculated when you don't set it.
85
+ # will automatically be calculated when you don't set it. (Deprecated)
86
86
  def initialize(path, language, screen_size = nil)
87
+ UI.deprecated('`screen_size` for Deliver::AppScreenshot.new is deprecated in favor of the default behavior to calculate size automatically. Passed value is no longer validated.') if screen_size
87
88
  self.path = path
88
89
  self.language = language
89
- screen_size ||= self.class.calculate_screen_size(path)
90
-
91
- self.screen_size = screen_size
92
-
93
- UI.error("Looks like the screenshot given (#{path}) does not match the requirements of #{screen_size}") unless self.is_valid?
90
+ self.screen_size = screen_size || self.class.calculate_screen_size(path)
94
91
  end
95
92
 
96
93
  # The iTC API requires a different notation for the device
@@ -161,6 +158,7 @@ module Deliver
161
158
 
162
159
  # Validates the given screenshots (size and format)
163
160
  def is_valid?
161
+ UI.deprecated('Deliver::AppScreenshot#is_valid? is deprecated in favor of Deliver::AppScreenshotValidator')
164
162
  return false unless ["png", "PNG", "jpg", "JPG", "jpeg", "JPEG"].include?(self.path.split(".").last)
165
163
 
166
164
  return self.screen_size == self.class.calculate_screen_size(self.path)
@@ -350,7 +348,7 @@ module Deliver
350
348
  end
351
349
  end
352
350
 
353
- UI.user_error!("Unsupported screen size #{size} for path '#{path}'")
351
+ nil
354
352
  end
355
353
  end
356
354
 
@@ -0,0 +1,108 @@
1
+ require 'fastimage'
2
+
3
+ module Deliver
4
+ class AppScreenshotValidator
5
+ # A simple structure that holds error information as well as formatted error messages consistently
6
+ # Set `to_skip` to `true` when just needing to skip uploading rather than causing a crash.
7
+ class ValidationError
8
+ # Constants that can be given to `type` param
9
+ INVALID_SCREEN_SIZE = 'Invalid screen size'.freeze
10
+ UNACCEPTABLE_DEVICE = 'Not an accepted App Store Connect device'.freeze
11
+ INVALID_FILE_EXTENSION = 'Invalid file extension'.freeze
12
+ FILE_EXTENSION_MISMATCH = 'File extension mismatches its image format'.freeze
13
+
14
+ attr_reader :type, :path, :debug_info, :to_skip
15
+
16
+ def initialize(type: nil, path: nil, debug_info: nil, to_skip: false)
17
+ @type = type
18
+ @path = path
19
+ @debug_info = debug_info
20
+ @to_skip = to_skip
21
+ end
22
+
23
+ def to_s
24
+ "#{to_skip ? '🏃 Skipping' : '🚫 Error'}: #{path} - #{type} (#{debug_info})"
25
+ end
26
+
27
+ def inspect
28
+ "\"#{type}\""
29
+ end
30
+ end
31
+
32
+ # Access each array by symbol returned from FastImage.type
33
+ ALLOWED_SCREENSHOT_FILE_EXTENSION = { png: ['png', 'PNG'], jpeg: ['jpg', 'JPG', 'jpeg', 'JPEG'] }.freeze
34
+
35
+ APP_SCREENSHOT_SPEC_URL = 'https://help.apple.com/app-store-connect/#/devd274dd925'.freeze
36
+
37
+ # Validate a screenshot and inform an error message via `errors` parameter. `errors` is mutated
38
+ # to append the messages and each message should contain the corresponding path to let users know which file is throwing the error.
39
+ #
40
+ # @param screenshot [AppScreenshot]
41
+ # @param errors [Array<Deliver::AppScreenshotValidator::ValidationError>] Pass an array object to add validation errors when detecting errors.
42
+ # This will be mutated to add more error objects as validation detects errors.
43
+ # @return [Boolean] true if given screenshot is valid
44
+ def self.validate(screenshot, errors)
45
+ # Given screenshot will be diagnosed and errors found are accumulated
46
+ errors_found = []
47
+
48
+ validate_screen_size(screenshot, errors_found)
49
+ validate_device_type(screenshot, errors_found)
50
+ validate_file_extension_and_format(screenshot, errors_found)
51
+
52
+ # Merge errors found into given errors array
53
+ errors_found.each { |error| errors.push(error) }
54
+ errors_found.empty?
55
+ end
56
+
57
+ def self.validate_screen_size(screenshot, errors_found)
58
+ if screenshot.screen_size.nil?
59
+ errors_found << ValidationError.new(type: ValidationError::INVALID_SCREEN_SIZE,
60
+ path: screenshot.path,
61
+ debug_info: "Actual size is #{get_formatted_size(screenshot)}. See the specifications to fix #{APP_SCREENSHOT_SPEC_URL}")
62
+ end
63
+ end
64
+
65
+ # Checking if the device type exists in spaceship
66
+ # Ex: iPhone 6.1 inch isn't supported in App Store Connect but need
67
+ # to have it in there for frameit support
68
+ def self.validate_device_type(screenshot, errors_found)
69
+ if !screenshot.screen_size.nil? && screenshot.device_type.nil?
70
+ errors_found << ValidationError.new(type: ValidationError::UNACCEPTABLE_DEVICE,
71
+ path: screenshot.path,
72
+ debug_info: "Screen size #{screenshot.screen_size} is not accepted. See the specifications to fix #{APP_SCREENSHOT_SPEC_URL}",
73
+ to_skip: true)
74
+ end
75
+ end
76
+
77
+ def self.validate_file_extension_and_format(screenshot, errors_found)
78
+ extension = File.extname(screenshot.path).delete('.')
79
+ valid_file_extensions = ALLOWED_SCREENSHOT_FILE_EXTENSION.values.flatten
80
+ is_valid_extension = valid_file_extensions.include?(extension)
81
+
82
+ unless is_valid_extension
83
+ errors_found << ValidationError.new(type: ValidationError::INVALID_FILE_EXTENSION,
84
+ path: screenshot.path,
85
+ debug_info: "Only #{valid_file_extensions.join(', ')} are allowed")
86
+ end
87
+
88
+ format = FastImage.type(screenshot.path)
89
+ is_extension_matched = ALLOWED_SCREENSHOT_FILE_EXTENSION[format] &&
90
+ ALLOWED_SCREENSHOT_FILE_EXTENSION[format].include?(extension)
91
+
92
+ # This error only appears when file extension is valid
93
+ if is_valid_extension && !is_extension_matched
94
+ expected_extension = ALLOWED_SCREENSHOT_FILE_EXTENSION[format].first
95
+ expected_filename = File.basename(screenshot.path, File.extname(screenshot.path)) + ".#{expected_extension}"
96
+ errors_found << ValidationError.new(type: ValidationError::FILE_EXTENSION_MISMATCH,
97
+ path: screenshot.path,
98
+ debug_info: %(Actual format is "#{format}". Rename the filename to "#{expected_filename}".))
99
+ end
100
+ end
101
+
102
+ def self.get_formatted_size(screenshot)
103
+ size = FastImage.size(screenshot.path)
104
+ return size.join('x') if size
105
+ nil
106
+ end
107
+ end
108
+ end
@@ -177,7 +177,7 @@ module Deliver
177
177
  end
178
178
  end
179
179
 
180
- Deliver::Setup.new.generate_metadata_files(app, v, path)
180
+ Deliver::Setup.new.generate_metadata_files(app, v, path, options)
181
181
  end
182
182
  end
183
183
 
@@ -1,8 +1,6 @@
1
- require 'fastlane_core/languages'
2
- require 'spaceship/tunes/tunes'
3
-
4
1
  require_relative 'module'
5
2
  require_relative 'app_screenshot'
3
+ require_relative 'app_screenshot_validator'
6
4
  require_relative 'upload_metadata'
7
5
  require_relative 'languages'
8
6
 
@@ -80,7 +78,7 @@ module Deliver
80
78
  end
81
79
  end
82
80
 
83
- # Returns the list of valid app screenshot
81
+ # Returns the list of valid app screenshot. When detecting invalid screenshots, this will cause an error.
84
82
  #
85
83
  # @param root [String] A directory path
86
84
  # @param ignore_validation [String] Set false not to raise the error when finding invalid folder name
@@ -100,36 +98,22 @@ module Deliver
100
98
  end
101
99
 
102
100
  errors = []
103
- valid_screenshots = screenshots.select { |screenshot| validate_screenshot(screenshot, errors) }
101
+ valid_screenshots = screenshots.select { |screenshot| Deliver::AppScreenshotValidator.validate(screenshot, errors) }
104
102
 
105
- unless errors.empty?
106
- UI.important("Unaccepted device screenshots are detected! 🚫 Screenshot file will be skipped. 🏃")
107
- errors.each { |error| UI.important(error) }
108
- end
103
+ errors_to_skip, errors_to_crash = errors.partition(&:to_skip)
109
104
 
110
- valid_screenshots
111
- end
105
+ unless errors_to_skip.empty?
106
+ UI.important("🏃 Screenshots to be skipped are detected!")
107
+ errors_to_skip.each { |error| UI.message(error) }
108
+ end
112
109
 
113
- # Validate a screenshot and inform an error message via `errors` parameters. `errors` is mutated
114
- # to append the messages and each message should contain the corresponding path to let users know which file gets the error.
115
- #
116
- # @param screenshot [AppScreenshot]
117
- # @param errors [Array<String>] Pass an array object to add error messages when finding an error
118
- # @return [Boolean] true if given screenshot is valid
119
- def self.validate_screenshot(screenshot, errors)
120
- # Given screenshot will be diagnosed and errors found are accumulated
121
- errors_found = []
122
-
123
- # Checking if the device type exists in spaceship
124
- # Ex: iPhone 6.1 inch isn't supported in App Store Connect but need
125
- # to have it in there for frameit support
126
- if screenshot.device_type.nil?
127
- errors_found << "🏃 Skipping screenshot file: #{screenshot.path} - Not an accepted App Store Connect device..."
110
+ unless errors_to_crash.empty?
111
+ UI.important("🚫 Invalid screenshots were detected! Here are the reasons:")
112
+ errors_to_crash.each { |error| UI.error(error) }
113
+ UI.user_error!("Canceled uploading screenshots. Please check the error messages above and fix the screenshots.")
128
114
  end
129
115
 
130
- # Merge errors found into given errors array
131
- errors_found.each { |error| errors.push(error) }
132
- errors_found.empty?
116
+ valid_screenshots
133
117
  end
134
118
 
135
119
  # Returns the list of language folders