fastlane 2.164.0 → 2.169.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 (117) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +80 -80
  3. data/cert/lib/cert/.options.rb.swp +0 -0
  4. data/cert/lib/cert/.runner.rb.swp +0 -0
  5. data/cert/lib/cert/options.rb +3 -3
  6. data/cert/lib/cert/runner.rb +2 -2
  7. data/deliver/lib/deliver/app_screenshot.rb +6 -2
  8. data/deliver/lib/deliver/loader.rb +136 -18
  9. data/deliver/lib/deliver/upload_metadata.rb +4 -10
  10. data/deliver/lib/deliver/upload_screenshots.rb +1 -64
  11. data/fastlane/lib/fastlane/actions/.download_dsyms.rb.swp +0 -0
  12. data/fastlane/lib/fastlane/actions/actions_helper.rb +1 -1
  13. data/fastlane/lib/fastlane/actions/add_git_tag.rb +9 -2
  14. data/fastlane/lib/fastlane/actions/appledoc.rb +1 -1
  15. data/fastlane/lib/fastlane/actions/docs/capture_ios_screenshots.md +4 -0
  16. data/fastlane/lib/fastlane/actions/docs/frame_screenshots.md +1 -1
  17. data/fastlane/lib/fastlane/actions/slather.rb +2 -2
  18. data/fastlane/lib/fastlane/actions/spm.rb +6 -0
  19. data/fastlane/lib/fastlane/actions/update_fastlane.rb +29 -8
  20. data/fastlane/lib/fastlane/actions/upload_to_app_store.rb +3 -3
  21. data/fastlane/lib/fastlane/actions/xcode_install.rb +8 -5
  22. data/fastlane/lib/fastlane/cli_tools_distributor.rb +2 -2
  23. data/fastlane/lib/fastlane/features.rb +1 -1
  24. data/fastlane/lib/fastlane/plugins/template/.rubocop.yml +1 -0
  25. data/fastlane/lib/fastlane/swift_fastlane_function.rb +1 -1
  26. data/fastlane/lib/fastlane/version.rb +1 -1
  27. data/fastlane/swift/Deliverfile.swift +1 -1
  28. data/fastlane/swift/DeliverfileProtocol.swift +1 -1
  29. data/fastlane/swift/Fastfile.swift +1 -1
  30. data/fastlane/swift/Fastlane.swift +56 -26
  31. data/fastlane/swift/Gymfile.swift +1 -1
  32. data/fastlane/swift/GymfileProtocol.swift +5 -1
  33. data/fastlane/swift/LaneFileProtocol.swift +2 -2
  34. data/fastlane/swift/MainProcess.swift +2 -0
  35. data/fastlane/swift/Matchfile.swift +1 -1
  36. data/fastlane/swift/MatchfileProtocol.swift +4 -4
  37. data/fastlane/swift/Precheckfile.swift +1 -1
  38. data/fastlane/swift/PrecheckfileProtocol.swift +1 -1
  39. data/fastlane/swift/Runner.swift +1 -1
  40. data/fastlane/swift/Scanfile.swift +1 -1
  41. data/fastlane/swift/ScanfileProtocol.swift +9 -1
  42. data/fastlane/swift/Screengrabfile.swift +1 -1
  43. data/fastlane/swift/ScreengrabfileProtocol.swift +1 -1
  44. data/fastlane/swift/Snapshotfile.swift +1 -1
  45. data/fastlane/swift/SnapshotfileProtocol.swift +1 -1
  46. data/fastlane/swift/SocketClient.swift +1 -1
  47. data/fastlane_core/lib/fastlane_core/cert_checker.rb +12 -7
  48. data/fastlane_core/lib/fastlane_core/helper.rb +10 -2
  49. data/fastlane_core/lib/fastlane_core/itunes_transporter.rb +3 -3
  50. data/fastlane_core/lib/fastlane_core/provisioning_profile.rb +3 -1
  51. data/fastlane_core/lib/fastlane_core/ui/disable_colors.rb +8 -0
  52. data/gym/lib/gym/code_signing_mapping.rb +1 -1
  53. data/gym/lib/gym/generators/build_command_generator.rb +1 -0
  54. data/gym/lib/gym/options.rb +7 -1
  55. data/match/lib/match/.options.rb.swp +0 -0
  56. data/match/lib/match/module.rb +1 -1
  57. data/match/lib/match/nuke.rb +9 -5
  58. data/match/lib/match/options.rb +2 -2
  59. data/pilot/lib/pilot/build_manager.rb +9 -3
  60. data/scan/lib/scan/detect_values.rb +3 -1
  61. data/scan/lib/scan/module.rb +4 -0
  62. data/scan/lib/scan/options.rb +16 -1
  63. data/scan/lib/scan/runner.rb +2 -2
  64. data/scan/lib/scan/test_command_generator.rb +1 -0
  65. data/{match/lib/match/.commands_generator.rb.swp → sigh/lib/sigh/.options.rb.swp} +0 -0
  66. data/sigh/lib/sigh/runner.rb +2 -2
  67. data/snapshot/lib/assets/SnapshotHelper.swift +5 -1
  68. data/snapshot/lib/snapshot/test_command_generator.rb +1 -1
  69. data/snapshot/lib/snapshot/test_command_generator_base.rb +3 -1
  70. data/snapshot/lib/snapshot/test_command_generator_xcode_8.rb +1 -1
  71. data/spaceship/lib/spaceship/client.rb +14 -0
  72. data/spaceship/lib/spaceship/connect_api.rb +2 -0
  73. data/spaceship/lib/spaceship/connect_api/client.rb +7 -4
  74. data/spaceship/lib/spaceship/connect_api/models/age_rating_declaration.rb +3 -2
  75. data/spaceship/lib/spaceship/connect_api/models/app.rb +139 -54
  76. data/spaceship/lib/spaceship/connect_api/models/app_info.rb +16 -10
  77. data/spaceship/lib/spaceship/connect_api/models/app_info_localization.rb +8 -4
  78. data/spaceship/lib/spaceship/connect_api/models/app_preview.rb +15 -11
  79. data/spaceship/lib/spaceship/connect_api/models/app_preview_set.rb +13 -9
  80. data/spaceship/lib/spaceship/connect_api/models/app_screenshot.rb +9 -7
  81. data/spaceship/lib/spaceship/connect_api/models/app_screenshot_set.rb +15 -11
  82. data/spaceship/lib/spaceship/connect_api/models/app_store_review_attachment.rb +7 -5
  83. data/spaceship/lib/spaceship/connect_api/models/app_store_review_detail.rb +6 -4
  84. data/spaceship/lib/spaceship/connect_api/models/app_store_version.rb +55 -36
  85. data/spaceship/lib/spaceship/connect_api/models/app_store_version_localization.rb +21 -14
  86. data/spaceship/lib/spaceship/connect_api/models/app_store_version_submission.rb +3 -2
  87. data/spaceship/lib/spaceship/connect_api/models/beta_app_review_submission.rb +3 -2
  88. data/spaceship/lib/spaceship/connect_api/models/beta_feedback.rb +6 -4
  89. data/spaceship/lib/spaceship/connect_api/models/beta_group.rb +12 -2
  90. data/spaceship/lib/spaceship/connect_api/models/beta_tester.rb +12 -8
  91. data/spaceship/lib/spaceship/connect_api/models/build.rb +24 -16
  92. data/spaceship/lib/spaceship/connect_api/models/build_delivery.rb +3 -2
  93. data/spaceship/lib/spaceship/connect_api/models/bundle_id.rb +9 -6
  94. data/spaceship/lib/spaceship/connect_api/models/bundle_id_capability.rb +6 -4
  95. data/spaceship/lib/spaceship/connect_api/models/certificate.rb +12 -8
  96. data/spaceship/lib/spaceship/connect_api/models/custom_app_organization.rb +43 -0
  97. data/spaceship/lib/spaceship/connect_api/models/custom_app_user.rb +41 -0
  98. data/spaceship/lib/spaceship/connect_api/models/device.rb +6 -4
  99. data/spaceship/lib/spaceship/connect_api/models/idfa_declaration.rb +6 -4
  100. data/spaceship/lib/spaceship/connect_api/models/profile.rb +12 -8
  101. data/spaceship/lib/spaceship/connect_api/models/reset_ratings_request.rb +3 -2
  102. data/spaceship/lib/spaceship/connect_api/models/sandbox_tester.rb +9 -6
  103. data/spaceship/lib/spaceship/connect_api/models/territory.rb +3 -2
  104. data/spaceship/lib/spaceship/connect_api/models/user.rb +6 -4
  105. data/spaceship/lib/spaceship/connect_api/models/user_invitation.rb +9 -6
  106. data/spaceship/lib/spaceship/connect_api/spaceship.rb +7 -4
  107. data/spaceship/lib/spaceship/connect_api/testflight/testflight.rb +12 -0
  108. data/spaceship/lib/spaceship/connect_api/tunes/tunes.rb +71 -0
  109. data/spaceship/lib/spaceship/errors.rb +19 -0
  110. data/spaceship/lib/spaceship/tunes/iap_detail.rb +1 -1
  111. data/spaceship/lib/spaceship/tunes/tunes_client.rb +2 -2
  112. data/spaceship/lib/spaceship/two_step_or_factor_client.rb +18 -6
  113. data/supply/lib/supply.rb +1 -1
  114. data/supply/lib/supply/options.rb +1 -1
  115. data/supply/lib/supply/uploader.rb +3 -2
  116. metadata +26 -22
  117. data/match/lib/match/.importer.rb.swp +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8cdb3738f1c646ea1cbff438e63895c5001d876fb9aeb585c1750ee61cbd86a4
4
- data.tar.gz: e19bd6d624de20687b690df55a2f906a69eecc9ea2ee45bf6ad6b58eb64c468c
3
+ metadata.gz: 89942043b1528ca3c3eff8b253e5c13a8fe910178b1670a553197f27260bb7d5
4
+ data.tar.gz: 476dffe7ef2b50121441191673e20041e4c91cdb8eecc5e1928a9f02930538b0
5
5
  SHA512:
6
- metadata.gz: da9f5620643df9f24fbded5fe29445ad72c9601d7c370a8092d1874ab22f629389fc9c43cbed71a8fa27667d91c425aa1666a581bbd2f1b34578dc0067ba4684
7
- data.tar.gz: a62090282896c1d8c65b2c789067a82f09f60089bc4fc963c104d4bfae0ef2d89e859484e744fd3e92e49f804c0d8cd5f315c6d5f392cd7bb1ee18f34efae631
6
+ metadata.gz: 26f4595813c6d3bdea582beabb32f4824b170dc660cf576d01aa1e6c696781e7538c6740bf09246f492ed06ac05a15db5eb0de88e21ccc07ed00e24b373c9380
7
+ data.tar.gz: e711d070232cecbcb7749c47c0fa6ac72e19b137753856c39de6739a55fd6159d4943575f784eb06070e12ba2d02ba5aea478481b48be8b9561a360e0756fa27
data/README.md CHANGED
@@ -34,61 +34,49 @@ 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='stefan-natchev'>
38
- <a href='https://github.com/snatchev'>
39
- <img src='https://github.com/snatchev.png?size=140'>
40
- </a>
41
- <h4 align='center'><a href='https://twitter.com/snatchev'>Stefan Natchev</a></h4>
42
- </td>
43
- <td id='olivier-halligon'>
44
- <a href='https://github.com/AliSoftware'>
45
- <img src='https://github.com/AliSoftware.png?size=140'>
46
- </a>
47
- <h4 align='center'><a href='https://twitter.com/aligatr'>Olivier Halligon</a></h4>
48
- </td>
49
- <td id='luka-mirosevic'>
50
- <a href='https://github.com/lmirosevic'>
51
- <img src='https://github.com/lmirosevic.png?size=140'>
52
- </a>
53
- <h4 align='center'><a href='https://twitter.com/lmirosevic'>Luka Mirosevic</a></h4>
54
- </td>
55
- <td id='joshua-liebowitz'>
56
- <a href='https://github.com/taquitos'>
57
- <img src='https://github.com/taquitos.png?size=140'>
58
- </a>
59
- <h4 align='center'><a href='https://twitter.com/taquitos'>Joshua Liebowitz</a></h4>
60
- </td>
61
- <td id='manu-wallner'>
62
- <a href='https://github.com/milch'>
63
- <img src='https://github.com/milch.png?size=140'>
37
+ <td id='josh-holtz'>
38
+ <a href='https://github.com/joshdholtz'>
39
+ <img src='https://github.com/joshdholtz.png?size=140'>
64
40
  </a>
65
- <h4 align='center'><a href='https://twitter.com/acrooow'>Manu Wallner</a></h4>
41
+ <h4 align='center'><a href='https://twitter.com/joshdholtz'>Josh Holtz</a></h4>
66
42
  </td>
67
- </tr>
68
- <tr>
69
43
  <td id='maksym-grebenets'>
70
44
  <a href='https://github.com/mgrebenets'>
71
45
  <img src='https://github.com/mgrebenets.png?size=140'>
72
46
  </a>
73
47
  <h4 align='center'><a href='https://twitter.com/mgrebenets'>Maksym Grebenets</a></h4>
74
48
  </td>
49
+ <td id='matthew-ellis'>
50
+ <a href='https://github.com/matthewellis'>
51
+ <img src='https://github.com/matthewellis.png?size=140'>
52
+ </a>
53
+ <h4 align='center'><a href='https://twitter.com/mellis1995'>Matthew Ellis</a></h4>
54
+ </td>
55
+ <td id='aaron-brager'>
56
+ <a href='https://github.com/getaaron'>
57
+ <img src='https://github.com/getaaron.png?size=140'>
58
+ </a>
59
+ <h4 align='center'><a href='https://twitter.com/getaaron'>Aaron Brager</a></h4>
60
+ </td>
75
61
  <td id='jorge-revuelta-h'>
76
62
  <a href='https://github.com/minuscorp'>
77
63
  <img src='https://github.com/minuscorp.png?size=140'>
78
64
  </a>
79
65
  <h4 align='center'><a href='https://twitter.com/minuscorp'>Jorge Revuelta H</a></h4>
80
66
  </td>
67
+ </tr>
68
+ <tr>
81
69
  <td id='jan-piotrowski'>
82
70
  <a href='https://github.com/janpio'>
83
71
  <img src='https://github.com/janpio.png?size=140'>
84
72
  </a>
85
73
  <h4 align='center'><a href='https://twitter.com/Sujan'>Jan Piotrowski</a></h4>
86
74
  </td>
87
- <td id='helmut-januschka'>
88
- <a href='https://github.com/hjanuschka'>
89
- <img src='https://github.com/hjanuschka.png?size=140'>
75
+ <td id='kohki-miki'>
76
+ <a href='https://github.com/giginet'>
77
+ <img src='https://github.com/giginet.png?size=140'>
90
78
  </a>
91
- <h4 align='center'><a href='https://twitter.com/hjanuschka'>Helmut Januschka</a></h4>
79
+ <h4 align='center'><a href='https://twitter.com/giginet'>Kohki Miki</a></h4>
92
80
  </td>
93
81
  <td id='max-ott'>
94
82
  <a href='https://github.com/max-ott'>
@@ -96,83 +84,95 @@ If the above doesn't help, please [submit an issue](https://github.com/fastlane/
96
84
  </a>
97
85
  <h4 align='center'><a href='https://twitter.com/ott_max'>Max Ott</a></h4>
98
86
  </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
+ <td id='fumiya-nakamura'>
94
+ <a href='https://github.com/nafu'>
95
+ <img src='https://github.com/nafu.png?size=140'>
96
+ </a>
97
+ <h4 align='center'><a href='https://twitter.com/nafu003'>Fumiya Nakamura</a></h4>
98
+ </td>
99
99
  </tr>
100
100
  <tr>
101
- <td id='matthew-ellis'>
102
- <a href='https://github.com/matthewellis'>
103
- <img src='https://github.com/matthewellis.png?size=140'>
101
+ <td id='felix-krause'>
102
+ <a href='https://github.com/KrauseFx'>
103
+ <img src='https://github.com/KrauseFx.png?size=140'>
104
104
  </a>
105
- <h4 align='center'><a href='https://twitter.com/mellis1995'>Matthew Ellis</a></h4>
105
+ <h4 align='center'><a href='https://twitter.com/KrauseFx'>Felix Krause</a></h4>
106
106
  </td>
107
- <td id='aaron-brager'>
108
- <a href='https://github.com/getaaron'>
109
- <img src='https://github.com/getaaron.png?size=140'>
107
+ <td id='daniel-jankowski'>
108
+ <a href='https://github.com/mollyIV'>
109
+ <img src='https://github.com/mollyIV.png?size=140'>
110
110
  </a>
111
- <h4 align='center'><a href='https://twitter.com/getaaron'>Aaron Brager</a></h4>
111
+ <h4 align='center'><a href='https://twitter.com/mollyIV'>Daniel Jankowski</a></h4>
112
112
  </td>
113
- <td id='josh-holtz'>
114
- <a href='https://github.com/joshdholtz'>
115
- <img src='https://github.com/joshdholtz.png?size=140'>
113
+ <td id='manu-wallner'>
114
+ <a href='https://github.com/milch'>
115
+ <img src='https://github.com/milch.png?size=140'>
116
116
  </a>
117
- <h4 align='center'><a href='https://twitter.com/joshdholtz'>Josh Holtz</a></h4>
117
+ <h4 align='center'><a href='https://twitter.com/acrooow'>Manu Wallner</a></h4>
118
118
  </td>
119
- <td id='jimmy-dee'>
120
- <a href='https://github.com/jdee'>
121
- <img src='https://github.com/jdee.png?size=140'>
119
+ <td id='helmut-januschka'>
120
+ <a href='https://github.com/hjanuschka'>
121
+ <img src='https://github.com/hjanuschka.png?size=140'>
122
122
  </a>
123
- <h4 align='center'>Jimmy Dee</h4>
123
+ <h4 align='center'><a href='https://twitter.com/hjanuschka'>Helmut Januschka</a></h4>
124
124
  </td>
125
- <td id='jérôme-lacoste'>
126
- <a href='https://github.com/lacostej'>
127
- <img src='https://github.com/lacostej.png?size=140'>
125
+ <td id='danielle-tomlinson'>
126
+ <a href='https://github.com/endocrimes'>
127
+ <img src='https://github.com/endocrimes.png?size=140'>
128
128
  </a>
129
- <h4 align='center'><a href='https://twitter.com/lacostej'>Jérôme Lacoste</a></h4>
129
+ <h4 align='center'><a href='https://twitter.com/endocrimes'>Danielle Tomlinson</a></h4>
130
130
  </td>
131
131
  </tr>
132
132
  <tr>
133
- <td id='daniel-jankowski'>
134
- <a href='https://github.com/mollyIV'>
135
- <img src='https://github.com/mollyIV.png?size=140'>
136
- </a>
137
- <h4 align='center'><a href='https://twitter.com/mollyIV'>Daniel Jankowski</a></h4>
138
- </td>
139
133
  <td id='andrew-mcburney'>
140
134
  <a href='https://github.com/armcburney'>
141
135
  <img src='https://github.com/armcburney.png?size=140'>
142
136
  </a>
143
137
  <h4 align='center'><a href='https://twitter.com/armcburney'>Andrew McBurney</a></h4>
144
138
  </td>
145
- <td id='kohki-miki'>
146
- <a href='https://github.com/giginet'>
147
- <img src='https://github.com/giginet.png?size=140'>
139
+ <td id='jérôme-lacoste'>
140
+ <a href='https://github.com/lacostej'>
141
+ <img src='https://github.com/lacostej.png?size=140'>
148
142
  </a>
149
- <h4 align='center'><a href='https://twitter.com/giginet'>Kohki Miki</a></h4>
143
+ <h4 align='center'><a href='https://twitter.com/lacostej'>Jérôme Lacoste</a></h4>
150
144
  </td>
151
- <td id='danielle-tomlinson'>
152
- <a href='https://github.com/endocrimes'>
153
- <img src='https://github.com/endocrimes.png?size=140'>
145
+ <td id='stefan-natchev'>
146
+ <a href='https://github.com/snatchev'>
147
+ <img src='https://github.com/snatchev.png?size=140'>
154
148
  </a>
155
- <h4 align='center'><a href='https://twitter.com/endocrimes'>Danielle Tomlinson</a></h4>
149
+ <h4 align='center'><a href='https://twitter.com/snatchev'>Stefan Natchev</a></h4>
156
150
  </td>
157
- <td id='iulian-onofrei'>
158
- <a href='https://github.com/revolter'>
159
- <img src='https://github.com/revolter.png?size=140'>
151
+ <td id='joshua-liebowitz'>
152
+ <a href='https://github.com/taquitos'>
153
+ <img src='https://github.com/taquitos.png?size=140'>
160
154
  </a>
161
- <h4 align='center'><a href='https://twitter.com/Revolt666'>Iulian Onofrei</a></h4>
155
+ <h4 align='center'><a href='https://twitter.com/taquitos'>Joshua Liebowitz</a></h4>
156
+ </td>
157
+ <td id='jimmy-dee'>
158
+ <a href='https://github.com/jdee'>
159
+ <img src='https://github.com/jdee.png?size=140'>
160
+ </a>
161
+ <h4 align='center'>Jimmy Dee</h4>
162
162
  </td>
163
163
  </tr>
164
164
  <tr>
165
- <td id='fumiya-nakamura'>
166
- <a href='https://github.com/nafu'>
167
- <img src='https://github.com/nafu.png?size=140'>
165
+ <td id='olivier-halligon'>
166
+ <a href='https://github.com/AliSoftware'>
167
+ <img src='https://github.com/AliSoftware.png?size=140'>
168
168
  </a>
169
- <h4 align='center'><a href='https://twitter.com/nafu003'>Fumiya Nakamura</a></h4>
169
+ <h4 align='center'><a href='https://twitter.com/aligatr'>Olivier Halligon</a></h4>
170
170
  </td>
171
- <td id='felix-krause'>
172
- <a href='https://github.com/KrauseFx'>
173
- <img src='https://github.com/KrauseFx.png?size=140'>
171
+ <td id='luka-mirosevic'>
172
+ <a href='https://github.com/lmirosevic'>
173
+ <img src='https://github.com/lmirosevic.png?size=140'>
174
174
  </a>
175
- <h4 align='center'><a href='https://twitter.com/KrauseFx'>Felix Krause</a></h4>
175
+ <h4 align='center'><a href='https://twitter.com/lmirosevic'>Luka Mirosevic</a></h4>
176
176
  </td>
177
177
  </table>
178
178
 
@@ -109,7 +109,7 @@ module Cert
109
109
  short_option: "-p",
110
110
  env_name: "CERT_KEYCHAIN_PASSWORD",
111
111
  sensitive: true,
112
- description: "This might be required the first time you access certificates on a new mac. For the login/default keychain this is your account password",
112
+ description: "This might be required the first time you access certificates on a new mac. For the login/default keychain this is your macOS account password",
113
113
  optional: true),
114
114
  FastlaneCore::ConfigItem.new(key: :skip_set_partition_list,
115
115
  short_option: "-P",
@@ -119,11 +119,11 @@ module Cert
119
119
  default_value: false),
120
120
  FastlaneCore::ConfigItem.new(key: :platform,
121
121
  env_name: "CERT_PLATFORM",
122
- description: "Set the provisioning profile's platform (ios, macos)",
122
+ description: "Set the provisioning profile's platform (ios, macos, tvos)",
123
123
  default_value: "ios",
124
124
  verify_block: proc do |value|
125
125
  value = value.to_s
126
- pt = %w(macos ios)
126
+ pt = %w(macos ios tvos)
127
127
  UI.user_error!("Unsupported platform, must be: #{pt}") unless pt.include?(value)
128
128
  end)
129
129
  ]
@@ -190,7 +190,7 @@ module Cert
190
190
  begin
191
191
  certificate = Spaceship::ConnectAPI::Certificate.create(
192
192
  certificate_type: certificate_type,
193
- csr_content: csr
193
+ csr_content: csr.to_pem
194
194
  )
195
195
  rescue => ex
196
196
  type_name = (Cert.config[:development] ? "Development" : "Distribution")
@@ -232,7 +232,7 @@ module Cert
232
232
  cert_name = "#{cert_name}.cer" unless File.extname(cert_name) == ".cer"
233
233
  path = File.expand_path(File.join(Cert.config[:output_path], cert_name))
234
234
  raw_data = Base64.decode64(certificate.certificate_content)
235
- File.write(path, raw_data)
235
+ File.write(path, raw_data.force_encoding("UTF-8"))
236
236
  return path
237
237
  end
238
238
  end
@@ -187,7 +187,9 @@ module Deliver
187
187
  return {
188
188
  ScreenSize::IOS_65_MESSAGES => [
189
189
  [1242, 2688],
190
- [2688, 1242]
190
+ [2688, 1242],
191
+ [1284, 2778],
192
+ [2778, 1284]
191
193
  ],
192
194
  ScreenSize::IOS_61_MESSAGES => [
193
195
  [828, 1792],
@@ -243,7 +245,9 @@ module Deliver
243
245
  return {
244
246
  ScreenSize::IOS_65 => [
245
247
  [1242, 2688],
246
- [2688, 1242]
248
+ [2688, 1242],
249
+ [1284, 2778],
250
+ [2778, 1284]
247
251
  ],
248
252
  ScreenSize::IOS_61 => [
249
253
  [828, 1792],
@@ -2,6 +2,7 @@ require 'fastlane_core/languages'
2
2
  require 'spaceship/tunes/tunes'
3
3
 
4
4
  require_relative 'module'
5
+ require_relative 'app_screenshot'
5
6
  require_relative 'upload_metadata'
6
7
  require_relative 'languages'
7
8
 
@@ -13,6 +14,7 @@ module Deliver
13
14
  IMESSAGE_DIR_NAME = "iMessage".freeze
14
15
  DEFAULT_DIR_NAME = "default".freeze
15
16
 
17
+ EXPANDABLE_DIR_NAMES = [APPLE_TV_DIR_NAME, IMESSAGE_DIR_NAME].freeze
16
18
  SPECIAL_DIR_NAMES = [APPLE_TV_DIR_NAME, IMESSAGE_DIR_NAME, DEFAULT_DIR_NAME].freeze
17
19
 
18
20
  # Some exception directories may exist from other actions that should not be iterated through
@@ -20,35 +22,151 @@ module Deliver
20
22
  FRAMEIT_FONTS_DIR_NAME = "fonts".freeze
21
23
  META_DIR_NAMES = UploadMetadata::ALL_META_SUB_DIRS.map(&:downcase)
22
24
 
23
- EXCEPTION_DIRECTORIES = (META_DIR_NAMES << SUPPLY_DIR_NAME << FRAMEIT_FONTS_DIR_NAME).freeze
25
+ EXCEPTION_DIRECTORIES = (META_DIR_NAMES << SUPPLY_DIR_NAME << FRAMEIT_FONTS_DIR_NAME).freeze
24
26
 
25
- def self.language_folders(root, ignore_validation)
26
- folders = Dir.glob(File.join(root, '*'))
27
+ # A class that represents language folder under screenshots or metadata folder
28
+ class LanguageFolder
29
+ attr_reader :path
30
+
31
+ # @return [String] A normalized language name that corresponds to the directory's name
32
+ attr_reader :language
33
+
34
+ def self.available_languages
35
+ # 2020-08-24 - Available locales are not available as an endpoint in App Store Connect
36
+ # Update with Spaceship::Tunes.client.available_languages.sort (as long as endpoint is avilable)
37
+ Deliver::Languages::ALL_LANGUAGES
38
+ end
39
+
40
+ def self.allowed_directory_names_with_case
41
+ available_languages + SPECIAL_DIR_NAMES
42
+ end
43
+
44
+ # @param path [String] A directory path otherwise this initializer fails
45
+ # @param nested [Boolan] Whether given path is nested of another special directory.
46
+ # This affects `expandable?` to return `false` when this set to `true`.
47
+ def initialize(path, nested: false)
48
+ raise(ArgumentError, "Given path must be a directory path - #{path}") unless File.directory?(path)
49
+ @path = path
50
+ @language = self.class.available_languages.find { |lang| basename.casecmp?(lang) }
51
+ @nested = nested
52
+ end
53
+
54
+ def nested?
55
+ @nested
56
+ end
57
+
58
+ def valid?
59
+ self.class.allowed_directory_names_with_case.any? { |name| name.casecmp?(basename) }
60
+ end
61
+
62
+ def expandable?
63
+ !nested? && EXPANDABLE_DIR_NAMES.any? { |name| name.casecmp?(basename) }
64
+ end
65
+
66
+ def skip?
67
+ EXCEPTION_DIRECTORIES.map(&:downcase).include?(basename.downcase)
68
+ end
69
+
70
+ def file_paths(extensions = '{png,jpg,jpeg}')
71
+ Dir.glob(File.join(path, "*.#{extensions}"), File::FNM_CASEFOLD).sort
72
+ end
27
73
 
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
74
+ def framed_file_paths(extensions = '{png,jpg,jpeg}')
75
+ Dir.glob(File.join(path, "*_framed.#{extensions}"), File::FNM_CASEFOLD).sort
76
+ end
77
+
78
+ def basename
79
+ File.basename(@path)
80
+ end
81
+ end
82
+
83
+ # Returns the list of valid app screenshot
84
+ #
85
+ # @param root [String] A directory path
86
+ # @param ignore_validation [String] Set false not to raise the error when finding invalid folder name
87
+ # @return [Array<AppScreenshot>] The list of AppScreenshot that exist under given `root` directory
88
+ def self.load_app_screenshots(root, ignore_validation)
89
+ screenshots = language_folders(root, ignore_validation, true).flat_map do |language_folder|
90
+ paths = if language_folder.framed_file_paths.count > 0
91
+ UI.important("Framed screenshots are detected! 🖼 Non-framed screenshot files may be skipped. 🏃")
92
+ # watchOS screenshots can be picked up even when framed ones were found since frameit doesn't support watchOS screenshots
93
+ framed_or_watch, skipped = language_folder.file_paths.partition { |path| path.downcase.include?('framed') || path.downcase.include?('watch') }
94
+ skipped.each { |path| UI.important("🏃 Skipping screenshot file: #{path}") }
95
+ framed_or_watch
96
+ else
97
+ language_folder.file_paths
98
+ end
99
+ paths.map { |path| AppScreenshot.new(path, language_folder.language) }
100
+ end
101
+
102
+ errors = []
103
+ valid_screenshots = screenshots.select { |screenshot| validate_screenshot(screenshot, errors) }
104
+
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
31
109
 
32
- allowed_directory_names_with_case = (available_languages + SPECIAL_DIR_NAMES)
33
- allowed_directory_names = allowed_directory_names_with_case.map(&:downcase).freeze
110
+ valid_screenshots
111
+ end
34
112
 
35
- selected_folders = folders.select do |path|
36
- File.directory?(path) && allowed_directory_names.include?(File.basename(path).downcase)
37
- end.sort
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 = []
38
122
 
39
- # Gets list of folders that are not supported languages
40
- rejected_folders = folders.select do |path|
41
- normalized_path = File.basename(path).downcase
42
- File.directory?(path) && !allowed_directory_names.include?(normalized_path) && !EXCEPTION_DIRECTORIES.include?(normalized_path)
43
- end.sort
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..."
128
+ end
129
+
130
+ # Merge errors found into given errors array
131
+ errors_found.each { |error| errors.push(error) }
132
+ errors_found.empty?
133
+ end
134
+
135
+ # Returns the list of language folders
136
+ #
137
+ # @param roort [String] A directory path to get the list of language folders
138
+ # @param ignore_validation [Boolean] Set false not to raise the error when finding invalid folder name
139
+ # @param expand_sub_folders [Boolean] Set true to expand special folders; such as "iMessage" to nested language folders
140
+ # @return [Array<LanguageFolder>] The list of LanguageFolder whose each of them
141
+ def self.language_folders(root, ignore_validation, expand_sub_folders = false)
142
+ folders = Dir.glob(File.join(root, '*'))
143
+ .select { |path| File.directory?(path) }
144
+ .map { |path| LanguageFolder.new(path, nested: false) }
145
+ .reject(&:skip?)
146
+
147
+ selected_folders, rejected_folders = folders.partition(&:valid?)
44
148
 
45
149
  if !ignore_validation && !rejected_folders.empty?
46
- rejected_folders = rejected_folders.map { |path| File.basename(path) }
150
+ rejected_folders = rejected_folders.map(&:basename)
47
151
  UI.user_error!("Unsupported directory name(s) for screenshots/metadata in '#{root}': #{rejected_folders.join(', ')}" \
48
- "\nValid directory names are: #{allowed_directory_names_with_case}" \
152
+ "\nValid directory names are: #{LanguageFolder.allowed_directory_names_with_case}" \
49
153
  "\n\nEnable 'ignore_language_directory_validation' to prevent this validation from happening")
50
154
  end
51
155
 
156
+ # Expand selected_folders for the special directories
157
+ if expand_sub_folders
158
+ selected_folders = selected_folders.flat_map do |folder|
159
+ if folder.expandable?
160
+ Dir.glob(File.join(folder.path, '*'))
161
+ .select { |p| File.directory?(p) }
162
+ .map { |p| LanguageFolder.new(p, nested: true) }
163
+ .select(&:valid?)
164
+ else
165
+ folder
166
+ end
167
+ end
168
+ end
169
+
52
170
  selected_folders
53
171
  end
54
172
  end