fastlane 2.212.2 → 2.214.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 (45) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +94 -94
  3. data/deliver/lib/deliver/upload_price_tier.rb +1 -1
  4. data/fastlane/lib/assets/custom_action_template.rb +18 -12
  5. data/fastlane/lib/fastlane/actions/docs/sync_code_signing.md +5 -3
  6. data/fastlane/lib/fastlane/actions/download_universal_apk_from_google_play.rb +124 -0
  7. data/fastlane/lib/fastlane/actions/ensure_git_status_clean.rb +31 -3
  8. data/fastlane/lib/fastlane/version.rb +1 -1
  9. data/fastlane/swift/Deliverfile.swift +1 -1
  10. data/fastlane/swift/DeliverfileProtocol.swift +1 -1
  11. data/fastlane/swift/Fastlane.swift +85 -6
  12. data/fastlane/swift/Gymfile.swift +1 -1
  13. data/fastlane/swift/GymfileProtocol.swift +1 -1
  14. data/fastlane/swift/Matchfile.swift +1 -1
  15. data/fastlane/swift/MatchfileProtocol.swift +5 -1
  16. data/fastlane/swift/Precheckfile.swift +1 -1
  17. data/fastlane/swift/PrecheckfileProtocol.swift +1 -1
  18. data/fastlane/swift/Scanfile.swift +1 -1
  19. data/fastlane/swift/ScanfileProtocol.swift +5 -1
  20. data/fastlane/swift/Screengrabfile.swift +1 -1
  21. data/fastlane/swift/ScreengrabfileProtocol.swift +1 -1
  22. data/fastlane/swift/Snapshotfile.swift +1 -1
  23. data/fastlane/swift/SnapshotfileProtocol.swift +1 -1
  24. data/fastlane/swift/formatting/Brewfile.lock.json +18 -18
  25. data/fastlane_core/lib/fastlane_core/cert_checker.rb +0 -5
  26. data/gym/lib/gym/generators/build_command_generator.rb +1 -1
  27. data/match/lib/match/importer.rb +1 -0
  28. data/match/lib/match/nuke.rb +1 -0
  29. data/match/lib/match/options.rb +5 -0
  30. data/match/lib/match/runner.rb +1 -0
  31. data/match/lib/match/storage/gitlab/client.rb +40 -14
  32. data/match/lib/match/storage/gitlab_secure_files.rb +17 -6
  33. data/pilot/lib/pilot/build_manager.rb +1 -1
  34. data/scan/lib/scan/detect_values.rb +8 -1
  35. data/scan/lib/scan/options.rb +5 -0
  36. data/scan/lib/scan/test_command_generator.rb +1 -1
  37. data/snapshot/lib/snapshot/test_command_generator.rb +1 -1
  38. data/spaceship/lib/spaceship/client.rb +0 -1
  39. data/spaceship/lib/spaceship/connect_api/models/user.rb +38 -0
  40. data/spaceship/lib/spaceship/connect_api/models/user_invitation.rb +5 -15
  41. data/spaceship/lib/spaceship/connect_api/users/users.rb +34 -0
  42. data/supply/lib/supply/client.rb +33 -0
  43. data/supply/lib/supply/generated_universal_apk.rb +24 -0
  44. data/supply/lib/supply.rb +1 -0
  45. metadata +30 -22
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 698222da63360e54a4d41e791a7ab1b2ac9331b348ef8626831d61a7261872de
4
- data.tar.gz: c89309b1a27610bd6f51dfad0b471ac908bbec30e981edf7b56485e5f83738f4
3
+ metadata.gz: c90da076e95e7d56aeb37df6dbd0f85ea6163ae1833e0ed048cb8e324c52b695
4
+ data.tar.gz: e0e11ef5984ec45bf0a8ac71b6ea2b635f5fe6f4e2f8244b6d701cee32d842c2
5
5
  SHA512:
6
- metadata.gz: fc46b26354a94f87f630a434fcb0f8387f9d84661da4b01aa9ea72f565a97f864d6fb6f2124a7a9342ae91c3f3c59657452f99c255bf0c418ae5da33d821af32
7
- data.tar.gz: 7198cdb4e60bf1c3c5b495307306a2888be696dd924a0e63aae7d787bdbfa5b4468d8a7f661f8fc741b79740801efcc603b32f912d9940a35373ec7230da5bd3
6
+ metadata.gz: 673b9f22b71d12323220280d414c45ba8b7c537b2b9c91c38ee9a46f9b7b4f7053c7fe0f9cc6583e4414608f3b755a154211e3b30ee202aeb59b282045ffb924
7
+ data.tar.gz: d8644326864b6f6895fd6c55a4ebc503cc2f730eb0dfce45201bab4bb4d8658b655e1746452d549793d47b234d2a8a8f7aad0c8bf246c7f46a8155eb556f5bde
data/README.md CHANGED
@@ -35,17 +35,43 @@ 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='maksym-grebenets'>
39
- <a href='https://github.com/mgrebenets'>
40
- <img src='https://github.com/mgrebenets.png' width='140px;'>
38
+ <td id='jorge-revuelta-h'>
39
+ <a href='https://github.com/minuscorp'>
40
+ <img src='https://github.com/minuscorp.png' width='140px;'>
41
41
  </a>
42
- <h4 align='center'><a href='https://twitter.com/mgrebenets'>Maksym Grebenets</a></h4>
42
+ <h4 align='center'><a href='https://twitter.com/minuscorp'>Jorge Revuelta H</a></h4>
43
43
  </td>
44
- <td id='iulian-onofrei'>
45
- <a href='https://github.com/revolter'>
46
- <img src='https://github.com/revolter.png' width='140px;'>
44
+ <td id='danielle-tomlinson'>
45
+ <a href='https://github.com/endocrimes'>
46
+ <img src='https://github.com/endocrimes.png' width='140px;'>
47
47
  </a>
48
- <h4 align='center'><a href='https://twitter.com/Revolt666'>Iulian Onofrei</a></h4>
48
+ <h4 align='center'><a href='https://twitter.com/endocrimes'>Danielle Tomlinson</a></h4>
49
+ </td>
50
+ <td id='jan-piotrowski'>
51
+ <a href='https://github.com/janpio'>
52
+ <img src='https://github.com/janpio.png' width='140px;'>
53
+ </a>
54
+ <h4 align='center'><a href='https://twitter.com/Sujan'>Jan Piotrowski</a></h4>
55
+ </td>
56
+ <td id='manish-rathi'>
57
+ <a href='https://github.com/crazymanish'>
58
+ <img src='https://github.com/crazymanish.png' width='140px;'>
59
+ </a>
60
+ <h4 align='center'><a href='https://twitter.com/iammanishrathi'>Manish Rathi</a></h4>
61
+ </td>
62
+ <td id='helmut-januschka'>
63
+ <a href='https://github.com/hjanuschka'>
64
+ <img src='https://github.com/hjanuschka.png' width='140px;'>
65
+ </a>
66
+ <h4 align='center'><a href='https://twitter.com/hjanuschka'>Helmut Januschka</a></h4>
67
+ </td>
68
+ </tr>
69
+ <tr>
70
+ <td id='roger-oba'>
71
+ <a href='https://github.com/rogerluan'>
72
+ <img src='https://github.com/rogerluan.png' width='140px;'>
73
+ </a>
74
+ <h4 align='center'><a href='https://twitter.com/rogerluan_'>Roger Oba</a></h4>
49
75
  </td>
50
76
  <td id='josh-holtz'>
51
77
  <a href='https://github.com/joshdholtz'>
@@ -53,63 +79,63 @@ If the above doesn't help, please [submit an issue](https://github.com/fastlane/
53
79
  </a>
54
80
  <h4 align='center'><a href='https://twitter.com/joshdholtz'>Josh Holtz</a></h4>
55
81
  </td>
56
- <td id='max-ott'>
57
- <a href='https://github.com/max-ott'>
58
- <img src='https://github.com/max-ott.png' width='140px;'>
82
+ <td id='iulian-onofrei'>
83
+ <a href='https://github.com/revolter'>
84
+ <img src='https://github.com/revolter.png' width='140px;'>
59
85
  </a>
60
- <h4 align='center'><a href='https://twitter.com/ott_max'>Max Ott</a></h4>
86
+ <h4 align='center'><a href='https://twitter.com/Revolt666'>Iulian Onofrei</a></h4>
61
87
  </td>
62
- <td id='olivier-halligon'>
63
- <a href='https://github.com/AliSoftware'>
64
- <img src='https://github.com/AliSoftware.png' width='140px;'>
88
+ <td id='felix-krause'>
89
+ <a href='https://github.com/KrauseFx'>
90
+ <img src='https://github.com/KrauseFx.png' width='140px;'>
65
91
  </a>
66
- <h4 align='center'><a href='https://twitter.com/aligatr'>Olivier Halligon</a></h4>
92
+ <h4 align='center'><a href='https://twitter.com/KrauseFx'>Felix Krause</a></h4>
93
+ </td>
94
+ <td id='jérôme-lacoste'>
95
+ <a href='https://github.com/lacostej'>
96
+ <img src='https://github.com/lacostej.png' width='140px;'>
97
+ </a>
98
+ <h4 align='center'><a href='https://twitter.com/lacostej'>Jérôme Lacoste</a></h4>
67
99
  </td>
68
100
  </tr>
69
101
  <tr>
70
- <td id='matthew-ellis'>
71
- <a href='https://github.com/matthewellis'>
72
- <img src='https://github.com/matthewellis.png' width='140px;'>
102
+ <td id='jimmy-dee'>
103
+ <a href='https://github.com/jdee'>
104
+ <img src='https://github.com/jdee.png' width='140px;'>
73
105
  </a>
74
- <h4 align='center'><a href='https://twitter.com/mellis1995'>Matthew Ellis</a></h4>
106
+ <h4 align='center'>Jimmy Dee</h4>
75
107
  </td>
76
- <td id='helmut-januschka'>
77
- <a href='https://github.com/hjanuschka'>
78
- <img src='https://github.com/hjanuschka.png' width='140px;'>
108
+ <td id='joshua-liebowitz'>
109
+ <a href='https://github.com/taquitos'>
110
+ <img src='https://github.com/taquitos.png' width='140px;'>
79
111
  </a>
80
- <h4 align='center'><a href='https://twitter.com/hjanuschka'>Helmut Januschka</a></h4>
112
+ <h4 align='center'><a href='https://twitter.com/taquitos'>Joshua Liebowitz</a></h4>
81
113
  </td>
82
- <td id='luka-mirosevic'>
83
- <a href='https://github.com/lmirosevic'>
84
- <img src='https://github.com/lmirosevic.png' width='140px;'>
114
+ <td id='max-ott'>
115
+ <a href='https://github.com/max-ott'>
116
+ <img src='https://github.com/max-ott.png' width='140px;'>
85
117
  </a>
86
- <h4 align='center'><a href='https://twitter.com/lmirosevic'>Luka Mirosevic</a></h4>
118
+ <h4 align='center'><a href='https://twitter.com/ott_max'>Max Ott</a></h4>
87
119
  </td>
88
- <td id='roger-oba'>
89
- <a href='https://github.com/rogerluan'>
90
- <img src='https://github.com/rogerluan.png' width='140px;'>
120
+ <td id='andrew-mcburney'>
121
+ <a href='https://github.com/armcburney'>
122
+ <img src='https://github.com/armcburney.png' width='140px;'>
91
123
  </a>
92
- <h4 align='center'><a href='https://twitter.com/rogerluan_'>Roger Oba</a></h4>
124
+ <h4 align='center'><a href='https://twitter.com/armcburney'>Andrew McBurney</a></h4>
93
125
  </td>
94
- <td id='łukasz-grabowski'>
95
- <a href='https://github.com/lucgrabowski'>
96
- <img src='https://github.com/lucgrabowski.png' width='140px;'>
126
+ <td id='satoshi-namai'>
127
+ <a href='https://github.com/ainame'>
128
+ <img src='https://github.com/ainame.png' width='140px;'>
97
129
  </a>
98
- <h4 align='center'>Łukasz Grabowski</h4>
130
+ <h4 align='center'><a href='https://twitter.com/ainame'>Satoshi Namai</a></h4>
99
131
  </td>
100
132
  </tr>
101
133
  <tr>
102
- <td id='jan-piotrowski'>
103
- <a href='https://github.com/janpio'>
104
- <img src='https://github.com/janpio.png' width='140px;'>
105
- </a>
106
- <h4 align='center'><a href='https://twitter.com/Sujan'>Jan Piotrowski</a></h4>
107
- </td>
108
- <td id='kohki-miki'>
109
- <a href='https://github.com/giginet'>
110
- <img src='https://github.com/giginet.png' width='140px;'>
134
+ <td id='maksym-grebenets'>
135
+ <a href='https://github.com/mgrebenets'>
136
+ <img src='https://github.com/mgrebenets.png' width='140px;'>
111
137
  </a>
112
- <h4 align='center'><a href='https://twitter.com/giginet'>Kohki Miki</a></h4>
138
+ <h4 align='center'><a href='https://twitter.com/mgrebenets'>Maksym Grebenets</a></h4>
113
139
  </td>
114
140
  <td id='aaron-brager'>
115
141
  <a href='https://github.com/getaaron'>
@@ -123,19 +149,11 @@ If the above doesn't help, please [submit an issue](https://github.com/fastlane/
123
149
  </a>
124
150
  <h4 align='center'><a href='https://twitter.com/mollyIV'>Daniel Jankowski</a></h4>
125
151
  </td>
126
- <td id='jorge-revuelta-h'>
127
- <a href='https://github.com/minuscorp'>
128
- <img src='https://github.com/minuscorp.png' width='140px;'>
129
- </a>
130
- <h4 align='center'><a href='https://twitter.com/minuscorp'>Jorge Revuelta H</a></h4>
131
- </td>
132
- </tr>
133
- <tr>
134
- <td id='danielle-tomlinson'>
135
- <a href='https://github.com/endocrimes'>
136
- <img src='https://github.com/endocrimes.png' width='140px;'>
152
+ <td id='luka-mirosevic'>
153
+ <a href='https://github.com/lmirosevic'>
154
+ <img src='https://github.com/lmirosevic.png' width='140px;'>
137
155
  </a>
138
- <h4 align='center'><a href='https://twitter.com/endocrimes'>Danielle Tomlinson</a></h4>
156
+ <h4 align='center'><a href='https://twitter.com/lmirosevic'>Luka Mirosevic</a></h4>
139
157
  </td>
140
158
  <td id='fumiya-nakamura'>
141
159
  <a href='https://github.com/nafu'>
@@ -143,17 +161,13 @@ If the above doesn't help, please [submit an issue](https://github.com/fastlane/
143
161
  </a>
144
162
  <h4 align='center'><a href='https://twitter.com/nafu003'>Fumiya Nakamura</a></h4>
145
163
  </td>
146
- <td id='felix-krause'>
147
- <a href='https://github.com/KrauseFx'>
148
- <img src='https://github.com/KrauseFx.png' width='140px;'>
149
- </a>
150
- <h4 align='center'><a href='https://twitter.com/KrauseFx'>Felix Krause</a></h4>
151
- </td>
152
- <td id='satoshi-namai'>
153
- <a href='https://github.com/ainame'>
154
- <img src='https://github.com/ainame.png' width='140px;'>
164
+ </tr>
165
+ <tr>
166
+ <td id='kohki-miki'>
167
+ <a href='https://github.com/giginet'>
168
+ <img src='https://github.com/giginet.png' width='140px;'>
155
169
  </a>
156
- <h4 align='center'><a href='https://twitter.com/ainame'>Satoshi Namai</a></h4>
170
+ <h4 align='center'><a href='https://twitter.com/giginet'>Kohki Miki</a></h4>
157
171
  </td>
158
172
  <td id='stefan-natchev'>
159
173
  <a href='https://github.com/snatchev'>
@@ -161,13 +175,11 @@ If the above doesn't help, please [submit an issue](https://github.com/fastlane/
161
175
  </a>
162
176
  <h4 align='center'><a href='https://twitter.com/snatchev'>Stefan Natchev</a></h4>
163
177
  </td>
164
- </tr>
165
- <tr>
166
- <td id='jimmy-dee'>
167
- <a href='https://github.com/jdee'>
168
- <img src='https://github.com/jdee.png' width='140px;'>
178
+ <td id='matthew-ellis'>
179
+ <a href='https://github.com/matthewellis'>
180
+ <img src='https://github.com/matthewellis.png' width='140px;'>
169
181
  </a>
170
- <h4 align='center'>Jimmy Dee</h4>
182
+ <h4 align='center'><a href='https://twitter.com/mellis1995'>Matthew Ellis</a></h4>
171
183
  </td>
172
184
  <td id='manu-wallner'>
173
185
  <a href='https://github.com/milch'>
@@ -175,31 +187,19 @@ If the above doesn't help, please [submit an issue](https://github.com/fastlane/
175
187
  </a>
176
188
  <h4 align='center'><a href='https://twitter.com/acrooow'>Manu Wallner</a></h4>
177
189
  </td>
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
- </a>
182
- <h4 align='center'><a href='https://twitter.com/lacostej'>Jérôme Lacoste</a></h4>
183
- </td>
184
- <td id='manish-rathi'>
185
- <a href='https://github.com/crazymanish'>
186
- <img src='https://github.com/crazymanish.png' width='140px;'>
187
- </a>
188
- <h4 align='center'><a href='https://twitter.com/iammanishrathi'>Manish Rathi</a></h4>
189
- </td>
190
- <td id='joshua-liebowitz'>
191
- <a href='https://github.com/taquitos'>
192
- <img src='https://github.com/taquitos.png' width='140px;'>
190
+ <td id='olivier-halligon'>
191
+ <a href='https://github.com/AliSoftware'>
192
+ <img src='https://github.com/AliSoftware.png' width='140px;'>
193
193
  </a>
194
- <h4 align='center'><a href='https://twitter.com/taquitos'>Joshua Liebowitz</a></h4>
194
+ <h4 align='center'><a href='https://twitter.com/aligatr'>Olivier Halligon</a></h4>
195
195
  </td>
196
196
  </tr>
197
197
  <tr>
198
- <td id='andrew-mcburney'>
199
- <a href='https://github.com/armcburney'>
200
- <img src='https://github.com/armcburney.png' width='140px;'>
198
+ <td id='łukasz-grabowski'>
199
+ <a href='https://github.com/lucgrabowski'>
200
+ <img src='https://github.com/lucgrabowski.png' width='140px;'>
201
201
  </a>
202
- <h4 align='center'><a href='https://twitter.com/armcburney'>Andrew McBurney</a></h4>
202
+ <h4 align='center'>Łukasz Grabowski</h4>
203
203
  </td>
204
204
  </table>
205
205
 
@@ -21,7 +21,7 @@ module Deliver
21
21
  # Need to get prices from the app's relationships
22
22
  # Prices from app's relationship doess not have price tier so need to fetch app price with price tier relationship
23
23
  app_prices = app.prices
24
- if app_prices.first
24
+ if app_prices&.first
25
25
  app_price = Spaceship::ConnectAPI.get_app_price(app_price_id: app_prices.first.id, includes: "priceTier").first
26
26
  old_price = app_price.price_tier.id
27
27
  else
@@ -7,7 +7,7 @@ module Fastlane
7
7
  class [[NAME_CLASS]] < Action
8
8
  def self.run(params)
9
9
  # fastlane will take care of reading in the parameter and fetching the environment variable:
10
- UI.message "Parameter API Token: #{params[:api_token]}"
10
+ UI.message("Parameter API Token: #{params[:api_token]}")
11
11
 
12
12
  # sh "shellcommand ./path"
13
13
 
@@ -19,13 +19,13 @@ module Fastlane
19
19
  #####################################################
20
20
 
21
21
  def self.description
22
- "A short description with <= 80 characters of what this action does"
22
+ 'A short description with <= 80 characters of what this action does'
23
23
  end
24
24
 
25
25
  def self.details
26
26
  # Optional:
27
27
  # this is your chance to provide a more detailed description of this action
28
- "You can use this action to do cool things..."
28
+ 'You can use this action to do cool things...'
29
29
  end
30
30
 
31
31
  def self.available_options
@@ -34,17 +34,23 @@ module Fastlane
34
34
  # Below a few examples
35
35
  [
36
36
  FastlaneCore::ConfigItem.new(key: :api_token,
37
- env_name: "FL_[[NAME_UP]]_API_TOKEN", # The name of the environment variable
38
- description: "API Token for [[NAME_CLASS]]", # a short description of this parameter
37
+ # The name of the environment variable
38
+ env_name: 'FL_[[NAME_UP]]_API_TOKEN',
39
+ # a short description of this parameter
40
+ description: 'API Token for [[NAME_CLASS]]',
39
41
  verify_block: proc do |value|
40
- UI.user_error!("No API token for [[NAME_CLASS]] given, pass using `api_token: 'token'`") unless (value and not value.empty?)
41
- # UI.user_error!("Couldn't find file at path '#{value}'") unless File.exist?(value)
42
+ unless value && !value.empty?
43
+ UI.user_error!("No API token for [[NAME_CLASS]] given, pass using `api_token: 'token'`")
44
+ end
45
+ # UI.user_error!("Couldn't find file at path '#{value}'") unless File.exist?(value)
42
46
  end),
43
47
  FastlaneCore::ConfigItem.new(key: :development,
44
- env_name: "FL_[[NAME_UP]]_DEVELOPMENT",
45
- description: "Create a development certificate instead of a distribution one",
46
- is_string: false, # true: verifies the input is a string, false: every kind of value
47
- default_value: false) # the default value if the user didn't provide one
48
+ env_name: 'FL_[[NAME_UP]]_DEVELOPMENT',
49
+ description: 'Create a development certificate instead of a distribution one',
50
+ # true: verifies the input is a string, false: every kind of value
51
+ is_string: false,
52
+ # the default value if the user didn't provide one
53
+ default_value: false)
48
54
  ]
49
55
  end
50
56
 
@@ -62,7 +68,7 @@ module Fastlane
62
68
 
63
69
  def self.authors
64
70
  # So no one will ever forget your contribution to fastlane :) You are awesome btw!
65
- ["Your GitHub/Twitter Name"]
71
+ ['Your GitHub/Twitter Name']
66
72
  end
67
73
 
68
74
  def self.is_supported?(platform)
@@ -212,7 +212,7 @@ fastlane match development
212
212
 
213
213
  <img src="/img/actions/match_appstore_small.gif" width="550" />
214
214
 
215
- This will create a new certificate and provisioning profile (if required) and store them in your selected storage.
215
+ This will create a new certificate and provisioning profile (if required) and store them in your selected storage.
216
216
  If you previously ran _match_ with the configured storage it will automatically install the existing profiles from your storage.
217
217
 
218
218
  The provisioning profiles are installed in `~/Library/MobileDevice/Provisioning Profiles` while the certificates and private keys are installed in your Keychain.
@@ -400,7 +400,7 @@ By using the `force_for_new_devices` parameter, _match_ will check if the (enabl
400
400
 
401
401
  _**Important:** The `force_for_new_devices` parameter is ignored for App Store provisioning profiles since they don't contain any device information._
402
402
 
403
- If you're not using _fastlane_, you can also use the `force_for_new_devices` option from the command line:
403
+ If you're not using `Fastfile`, you can also use the `force_for_new_devices` option from the command line:
404
404
 
405
405
  ```no-highlight
406
406
  fastlane match adhoc --force_for_new_devices
@@ -512,9 +512,11 @@ Please be careful when using this option and ensure the certificates and profile
512
512
  If you want to manually decrypt a file you can.
513
513
 
514
514
  ```no-highlight
515
- openssl aes-256-cbc -k "<password>" -in "<fileYouWantToDecryptPath>" -out "<decryptedFilePath>" -a -d
515
+ openssl aes-256-cbc -k "<password>" -in "<fileYouWantToDecryptPath>" -out "<decryptedFilePath>" -a -d -md [md5|sha256]
516
516
  ```
517
517
 
518
+ _**Note:** You may need to swap double quotes `"` for single quotes `'` if your match password contains an exclamation mark `!`._
519
+
518
520
  #### Export Distribution Certificate and Private Key as Single .p12 File
519
521
 
520
522
  _match_ stores the certificate (`.cer`) and the private key (`.p12`) files separately. The following steps will repackage the separate certificate and private key into a single `.p12` file.
@@ -0,0 +1,124 @@
1
+ require 'supply'
2
+ require 'supply/options'
3
+
4
+ module Fastlane
5
+ module Actions
6
+ class DownloadUniversalApkFromGooglePlayAction < Action
7
+ def self.run(params)
8
+ package_name = params[:package_name]
9
+ version_code = params[:version_code]
10
+ destination = params[:destination]
11
+ cert_sha = params[:certificate_sha256_hash]
12
+
13
+ client = Supply::Client.make_from_config(params: params)
14
+
15
+ UI.message("Fetching the list of generated APKs from the Google API...")
16
+ all_universal_apks = client.list_generated_universal_apks(package_name: package_name, version_code: version_code)
17
+ matching_apks = all_universal_apks.select { |apk| cert_sha.nil? || apk.certificate_sha256_hash&.casecmp?(cert_sha) }
18
+
19
+ all_certs_printable_list = all_universal_apks.map { |apk| " - #{apk.certificate_sha256_hash}" }
20
+ if matching_apks.count > 1
21
+ message = <<~ERROR
22
+ We found multiple Generated Universal APK, with the following `certificate_sha256_hash`:
23
+ #{all_certs_printable_list.join("\n")}
24
+
25
+ Use the `certificate_sha256_hash` parameter to specify which one to download.
26
+ ERROR
27
+ UI.user_error!(message)
28
+ elsif matching_apks.empty?
29
+ # NOTE: if no APK was found at all to begin with, the client would already have raised a user_error!('Google Api Error ...')
30
+ message = <<~ERROR
31
+ None of the Universal APK(s) found for this version code matched the `certificate_sha256_hash` of `#{cert_sha}`.
32
+
33
+ We found #{all_universal_apks.count} Generated Universal APK(s), but with a different `certificate_sha256_hash`:
34
+ #{all_certs_printable_list.join("\n")}
35
+ ERROR
36
+ UI.user_error!(message)
37
+ end
38
+
39
+ UI.message("Downloading Generated Universal APK to `#{destination}`...")
40
+ FileUtils.mkdir_p(File.dirname(destination))
41
+ client.download_generated_universal_apk(generated_universal_apk: matching_apks.first, destination: destination)
42
+
43
+ UI.success("Universal APK successfully downloaded to `#{destination}`.")
44
+ destination
45
+ end
46
+
47
+ #####################################################
48
+ # @!group Documentation
49
+ #####################################################
50
+
51
+ def self.description
52
+ "Download the Universal APK of a given version code from the Google Play Console"
53
+ end
54
+
55
+ def self.details
56
+ <<~DETAILS
57
+ Download the universal APK of a given version code from the Google Play Console.
58
+
59
+ This uses fastlane `Supply` (and the `AndroidPublisher` Google API) to download the Universal APK
60
+ generated by Google after you uploaded an `.aab` bundle to the Play Console.
61
+
62
+ See https://developers.google.com/android-publisher/api-ref/rest/v3/generatedapks/list
63
+ DETAILS
64
+ end
65
+
66
+ def self.available_options
67
+ # Only borrow _some_ of the ConfigItems from https://github.com/fastlane/fastlane/blob/master/supply/lib/supply/options.rb
68
+ # So we don't have to duplicate the name, env_var, type, description, and verify_block of those here.
69
+ supply_borrowed_options = Supply::Options.available_options.select do |o|
70
+ %i[package_name version_code json_key json_key_data root_url timeout].include?(o.key)
71
+ end
72
+ # Adjust the description for the :version_code ConfigItem for our action's use case
73
+ supply_borrowed_options.find { |o| o.key == :version_code }&.description = "The versionCode for which to download the generated APK"
74
+
75
+ [
76
+ *supply_borrowed_options,
77
+
78
+ # The remaining ConfigItems below are specific to this action
79
+ FastlaneCore::ConfigItem.new(key: :destination,
80
+ env_name: 'DOWNLOAD_UNIVERSAL_APK_DESTINATION',
81
+ optional: false,
82
+ type: String,
83
+ description: "The path on disk where to download the Generated Universal APK",
84
+ verify_block: proc do |value|
85
+ UI.user_error!("The 'destination' must be a file path with the `.apk` file extension") unless File.extname(value) == '.apk'
86
+ end),
87
+ FastlaneCore::ConfigItem.new(key: :certificate_sha256_hash,
88
+ env_name: 'DOWNLOAD_UNIVERSAL_APK_CERTIFICATE_SHA256_HASH',
89
+ optional: true,
90
+ type: String,
91
+ description: "The SHA256 hash of the signing key for which to download the Universal, Code-Signed APK for. " \
92
+ + "Use 'xx:xx:xx:…' format (32 hex bytes separated by colons), as printed by `keytool -list -keystore <keystorefile>`. " \
93
+ + "Only useful to provide if you have multiple signing keys configured on GPC, to specify which generated APK to download",
94
+ verify_block: proc do |value|
95
+ bytes = value.split(':')
96
+ next if bytes.length == 32 && bytes.all? { |byte| /^[0-9a-fA-F]{2}$/.match?(byte) }
97
+
98
+ UI.user_error!("When provided, the certificate sha256 must be in the 'xx:xx:xx:…:xx' (32 hex bytes separated by colons) format")
99
+ end)
100
+ ]
101
+ end
102
+
103
+ def self.output
104
+ # Define the shared values you are going to provide
105
+ end
106
+
107
+ def self.return_value
108
+ 'The path to the downloaded Universal APK. The action will raise an exception if it failed to find or download the APK in Google Play'
109
+ end
110
+
111
+ def self.authors
112
+ ['Automattic']
113
+ end
114
+
115
+ def self.category
116
+ :production
117
+ end
118
+
119
+ def self.is_supported?(platform)
120
+ platform == :android
121
+ end
122
+ end
123
+ end
124
+ end
@@ -7,12 +7,35 @@ module Fastlane
7
7
  # Raises an exception and stop the lane execution if the repo is not in a clean state
8
8
  class EnsureGitStatusCleanAction < Action
9
9
  def self.run(params)
10
+ # Build command
10
11
  if params[:ignored]
11
12
  ignored_mode = params[:ignored]
12
13
  ignored_mode = 'no' if ignored_mode == 'none'
13
- repo_status = Actions.sh("git status --porcelain --ignored='#{ignored_mode}'")
14
+ command = "git status --porcelain --ignored='#{ignored_mode}'"
14
15
  else
15
- repo_status = Actions.sh("git status --porcelain")
16
+ command = "git status --porcelain"
17
+ end
18
+
19
+ # Don't log if manually ignoring files as it will emulate output later
20
+ print_output = params[:ignore_files].nil?
21
+ repo_status = Actions.sh(command, log: print_output)
22
+
23
+ # Manual post processing trying to ignore certain file paths
24
+ if (ignore_files = params[:ignore_files])
25
+ repo_status = repo_status.lines.reject do |line|
26
+ path = line.split(' ').last
27
+ was_found = ignore_files.include?(path)
28
+
29
+ UI.message("Ignoring '#{path}'") if was_found
30
+
31
+ was_found
32
+ end.join("")
33
+
34
+ # Emulate the output format of `git status --porcelain`
35
+ UI.command(command)
36
+ repo_status.lines.each do |line|
37
+ UI.message("▸ " + line.chomp.magenta)
38
+ end
16
39
  end
17
40
 
18
41
  repo_clean = repo_status.empty?
@@ -86,7 +109,12 @@ module Fastlane
86
109
  modes = %w(traditional none matching)
87
110
 
88
111
  UI.user_error!("Unsupported mode, must be: #{modes}") unless modes.include?(mode)
89
- end)
112
+ end),
113
+ FastlaneCore::ConfigItem.new(key: :ignore_files,
114
+ env_name: "FL_ENSURE_GIT_STATUS_CLEAN_IGNORE_FILES",
115
+ description: "Array of files to ignore",
116
+ optional: true,
117
+ type: Array)
90
118
  ]
91
119
  end
92
120
 
@@ -1,5 +1,5 @@
1
1
  module Fastlane
2
- VERSION = '2.212.2'.freeze
2
+ VERSION = '2.214.0'.freeze
3
3
  DESCRIPTION = "The easiest way to automate beta deployments and releases for your iOS and Android apps".freeze
4
4
  MINIMUM_XCODE_RELEASE = "7.0".freeze
5
5
  RUBOCOP_REQUIREMENT = '1.12.1'.freeze
@@ -17,4 +17,4 @@ public class Deliverfile: DeliverfileProtocol {
17
17
  // during the `init` process, and you won't see this message
18
18
  }
19
19
 
20
- // Generated with fastlane 2.212.2
20
+ // Generated with fastlane 2.214.0
@@ -264,4 +264,4 @@ public extension DeliverfileProtocol {
264
264
 
265
265
  // Please don't remove the lines below
266
266
  // They are used to detect outdated files
267
- // FastlaneRunnerAPIVersion [0.9.115]
267
+ // FastlaneRunnerAPIVersion [0.9.117]