fastlane 2.213.0 → 2.214.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +92 -92
  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/version.rb +1 -1
  8. data/fastlane/swift/Deliverfile.swift +1 -1
  9. data/fastlane/swift/DeliverfileProtocol.swift +1 -1
  10. data/fastlane/swift/Fastlane.swift +59 -4
  11. data/fastlane/swift/Gymfile.swift +1 -1
  12. data/fastlane/swift/GymfileProtocol.swift +1 -1
  13. data/fastlane/swift/Matchfile.swift +1 -1
  14. data/fastlane/swift/MatchfileProtocol.swift +1 -1
  15. data/fastlane/swift/Precheckfile.swift +1 -1
  16. data/fastlane/swift/PrecheckfileProtocol.swift +1 -1
  17. data/fastlane/swift/Scanfile.swift +1 -1
  18. data/fastlane/swift/ScanfileProtocol.swift +1 -1
  19. data/fastlane/swift/Screengrabfile.swift +1 -1
  20. data/fastlane/swift/ScreengrabfileProtocol.swift +1 -1
  21. data/fastlane/swift/Snapshotfile.swift +1 -1
  22. data/fastlane/swift/SnapshotfileProtocol.swift +1 -1
  23. data/fastlane/swift/formatting/Brewfile.lock.json +18 -18
  24. data/gym/lib/gym/generators/build_command_generator.rb +1 -1
  25. data/match/lib/match/storage/gitlab/client.rb +40 -14
  26. data/match/lib/match/storage/gitlab_secure_files.rb +7 -2
  27. data/scan/lib/scan/test_command_generator.rb +1 -1
  28. data/snapshot/lib/snapshot/test_command_generator.rb +1 -1
  29. data/spaceship/lib/spaceship/client.rb +0 -1
  30. data/spaceship/lib/spaceship/connect_api/models/user.rb +38 -0
  31. data/spaceship/lib/spaceship/connect_api/models/user_invitation.rb +5 -15
  32. data/spaceship/lib/spaceship/connect_api/users/users.rb +34 -0
  33. data/supply/lib/supply/client.rb +33 -0
  34. data/supply/lib/supply/generated_universal_apk.rb +24 -0
  35. data/supply/lib/supply.rb +1 -0
  36. metadata +22 -20
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4ac7eee0c8810536692c5ffca62c0f0924595f223d889affb732cb72f98e64be
4
- data.tar.gz: 6d91512766cfd352f98cfa4fc905f366bd4c6eefe8ddf680ddddb1e222827120
3
+ metadata.gz: c90da076e95e7d56aeb37df6dbd0f85ea6163ae1833e0ed048cb8e324c52b695
4
+ data.tar.gz: e0e11ef5984ec45bf0a8ac71b6ea2b635f5fe6f4e2f8244b6d701cee32d842c2
5
5
  SHA512:
6
- metadata.gz: e7ebfc7fcd8d9883e053fe32e277a31aa70b98082532efdd310d7bd4b6e44976e4445e345c980f41b19baaa31ba6dcff626af80299393d97f83e45ff8f2c4558
7
- data.tar.gz: eec9c6e744bced6eacc16bd85c2cf86cc2e5cb920e2c031add3a0d5690b9e6b675b68d5bcb89db5cef48ec1367b2d6e610ac83eb9271c98e08f6ad0ba80225d8
6
+ metadata.gz: 673b9f22b71d12323220280d414c45ba8b7c537b2b9c91c38ee9a46f9b7b4f7053c7fe0f9cc6583e4414608f3b755a154211e3b30ee202aeb59b282045ffb924
7
+ data.tar.gz: d8644326864b6f6895fd6c55a4ebc503cc2f730eb0dfce45201bab4bb4d8658b655e1746452d549793d47b234d2a8a8f7aad0c8bf246c7f46a8155eb556f5bde
data/README.md CHANGED
@@ -35,11 +35,17 @@ 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='daniel-jankowski'>
39
- <a href='https://github.com/mollyIV'>
40
- <img src='https://github.com/mollyIV.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/mollyIV'>Daniel Jankowski</a></h4>
42
+ <h4 align='center'><a href='https://twitter.com/minuscorp'>Jorge Revuelta H</a></h4>
43
+ </td>
44
+ <td id='danielle-tomlinson'>
45
+ <a href='https://github.com/endocrimes'>
46
+ <img src='https://github.com/endocrimes.png' width='140px;'>
47
+ </a>
48
+ <h4 align='center'><a href='https://twitter.com/endocrimes'>Danielle Tomlinson</a></h4>
43
49
  </td>
44
50
  <td id='jan-piotrowski'>
45
51
  <a href='https://github.com/janpio'>
@@ -47,107 +53,89 @@ If the above doesn't help, please [submit an issue](https://github.com/fastlane/
47
53
  </a>
48
54
  <h4 align='center'><a href='https://twitter.com/Sujan'>Jan Piotrowski</a></h4>
49
55
  </td>
50
- <td id='josh-holtz'>
51
- <a href='https://github.com/joshdholtz'>
52
- <img src='https://github.com/joshdholtz.png' width='140px;'>
53
- </a>
54
- <h4 align='center'><a href='https://twitter.com/joshdholtz'>Josh Holtz</a></h4>
55
- </td>
56
- <td id='manu-wallner'>
57
- <a href='https://github.com/milch'>
58
- <img src='https://github.com/milch.png' width='140px;'>
56
+ <td id='manish-rathi'>
57
+ <a href='https://github.com/crazymanish'>
58
+ <img src='https://github.com/crazymanish.png' width='140px;'>
59
59
  </a>
60
- <h4 align='center'><a href='https://twitter.com/acrooow'>Manu Wallner</a></h4>
60
+ <h4 align='center'><a href='https://twitter.com/iammanishrathi'>Manish Rathi</a></h4>
61
61
  </td>
62
- <td id='kohki-miki'>
63
- <a href='https://github.com/giginet'>
64
- <img src='https://github.com/giginet.png' width='140px;'>
62
+ <td id='helmut-januschka'>
63
+ <a href='https://github.com/hjanuschka'>
64
+ <img src='https://github.com/hjanuschka.png' width='140px;'>
65
65
  </a>
66
- <h4 align='center'><a href='https://twitter.com/giginet'>Kohki Miki</a></h4>
66
+ <h4 align='center'><a href='https://twitter.com/hjanuschka'>Helmut Januschka</a></h4>
67
67
  </td>
68
68
  </tr>
69
69
  <tr>
70
- <td id='jérôme-lacoste'>
71
- <a href='https://github.com/lacostej'>
72
- <img src='https://github.com/lacostej.png' width='140px;'>
73
- </a>
74
- <h4 align='center'><a href='https://twitter.com/lacostej'>Jérôme Lacoste</a></h4>
75
- </td>
76
- <td id='olivier-halligon'>
77
- <a href='https://github.com/AliSoftware'>
78
- <img src='https://github.com/AliSoftware.png' width='140px;'>
79
- </a>
80
- <h4 align='center'><a href='https://twitter.com/aligatr'>Olivier Halligon</a></h4>
81
- </td>
82
- <td id='danielle-tomlinson'>
83
- <a href='https://github.com/endocrimes'>
84
- <img src='https://github.com/endocrimes.png' width='140px;'>
85
- </a>
86
- <h4 align='center'><a href='https://twitter.com/endocrimes'>Danielle Tomlinson</a></h4>
87
- </td>
88
70
  <td id='roger-oba'>
89
71
  <a href='https://github.com/rogerluan'>
90
72
  <img src='https://github.com/rogerluan.png' width='140px;'>
91
73
  </a>
92
74
  <h4 align='center'><a href='https://twitter.com/rogerluan_'>Roger Oba</a></h4>
93
75
  </td>
94
- <td id='luka-mirosevic'>
95
- <a href='https://github.com/lmirosevic'>
96
- <img src='https://github.com/lmirosevic.png' width='140px;'>
76
+ <td id='josh-holtz'>
77
+ <a href='https://github.com/joshdholtz'>
78
+ <img src='https://github.com/joshdholtz.png' width='140px;'>
97
79
  </a>
98
- <h4 align='center'><a href='https://twitter.com/lmirosevic'>Luka Mirosevic</a></h4>
80
+ <h4 align='center'><a href='https://twitter.com/joshdholtz'>Josh Holtz</a></h4>
99
81
  </td>
100
- </tr>
101
- <tr>
102
- <td id='łukasz-grabowski'>
103
- <a href='https://github.com/lucgrabowski'>
104
- <img src='https://github.com/lucgrabowski.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;'>
105
85
  </a>
106
- <h4 align='center'>Łukasz Grabowski</h4>
86
+ <h4 align='center'><a href='https://twitter.com/Revolt666'>Iulian Onofrei</a></h4>
107
87
  </td>
108
- <td id='matthew-ellis'>
109
- <a href='https://github.com/matthewellis'>
110
- <img src='https://github.com/matthewellis.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;'>
111
91
  </a>
112
- <h4 align='center'><a href='https://twitter.com/mellis1995'>Matthew Ellis</a></h4>
92
+ <h4 align='center'><a href='https://twitter.com/KrauseFx'>Felix Krause</a></h4>
113
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>
99
+ </td>
100
+ </tr>
101
+ <tr>
114
102
  <td id='jimmy-dee'>
115
103
  <a href='https://github.com/jdee'>
116
104
  <img src='https://github.com/jdee.png' width='140px;'>
117
105
  </a>
118
106
  <h4 align='center'>Jimmy Dee</h4>
119
107
  </td>
120
- <td id='max-ott'>
121
- <a href='https://github.com/max-ott'>
122
- <img src='https://github.com/max-ott.png' width='140px;'>
123
- </a>
124
- <h4 align='center'><a href='https://twitter.com/ott_max'>Max Ott</a></h4>
125
- </td>
126
- <td id='iulian-onofrei'>
127
- <a href='https://github.com/revolter'>
128
- <img src='https://github.com/revolter.png' width='140px;'>
129
- </a>
130
- <h4 align='center'><a href='https://twitter.com/Revolt666'>Iulian Onofrei</a></h4>
131
- </td>
132
- </tr>
133
- <tr>
134
108
  <td id='joshua-liebowitz'>
135
109
  <a href='https://github.com/taquitos'>
136
110
  <img src='https://github.com/taquitos.png' width='140px;'>
137
111
  </a>
138
112
  <h4 align='center'><a href='https://twitter.com/taquitos'>Joshua Liebowitz</a></h4>
139
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;'>
117
+ </a>
118
+ <h4 align='center'><a href='https://twitter.com/ott_max'>Max Ott</a></h4>
119
+ </td>
140
120
  <td id='andrew-mcburney'>
141
121
  <a href='https://github.com/armcburney'>
142
122
  <img src='https://github.com/armcburney.png' width='140px;'>
143
123
  </a>
144
124
  <h4 align='center'><a href='https://twitter.com/armcburney'>Andrew McBurney</a></h4>
145
125
  </td>
146
- <td id='manish-rathi'>
147
- <a href='https://github.com/crazymanish'>
148
- <img src='https://github.com/crazymanish.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;'>
149
129
  </a>
150
- <h4 align='center'><a href='https://twitter.com/iammanishrathi'>Manish Rathi</a></h4>
130
+ <h4 align='center'><a href='https://twitter.com/ainame'>Satoshi Namai</a></h4>
131
+ </td>
132
+ </tr>
133
+ <tr>
134
+ <td id='maksym-grebenets'>
135
+ <a href='https://github.com/mgrebenets'>
136
+ <img src='https://github.com/mgrebenets.png' width='140px;'>
137
+ </a>
138
+ <h4 align='center'><a href='https://twitter.com/mgrebenets'>Maksym Grebenets</a></h4>
151
139
  </td>
152
140
  <td id='aaron-brager'>
153
141
  <a href='https://github.com/getaaron'>
@@ -155,31 +143,31 @@ If the above doesn't help, please [submit an issue](https://github.com/fastlane/
155
143
  </a>
156
144
  <h4 align='center'><a href='https://twitter.com/getaaron'>Aaron Brager</a></h4>
157
145
  </td>
158
- <td id='satoshi-namai'>
159
- <a href='https://github.com/ainame'>
160
- <img src='https://github.com/ainame.png' width='140px;'>
146
+ <td id='daniel-jankowski'>
147
+ <a href='https://github.com/mollyIV'>
148
+ <img src='https://github.com/mollyIV.png' width='140px;'>
161
149
  </a>
162
- <h4 align='center'><a href='https://twitter.com/ainame'>Satoshi Namai</a></h4>
150
+ <h4 align='center'><a href='https://twitter.com/mollyIV'>Daniel Jankowski</a></h4>
151
+ </td>
152
+ <td id='luka-mirosevic'>
153
+ <a href='https://github.com/lmirosevic'>
154
+ <img src='https://github.com/lmirosevic.png' width='140px;'>
155
+ </a>
156
+ <h4 align='center'><a href='https://twitter.com/lmirosevic'>Luka Mirosevic</a></h4>
163
157
  </td>
164
- </tr>
165
- <tr>
166
158
  <td id='fumiya-nakamura'>
167
159
  <a href='https://github.com/nafu'>
168
160
  <img src='https://github.com/nafu.png' width='140px;'>
169
161
  </a>
170
162
  <h4 align='center'><a href='https://twitter.com/nafu003'>Fumiya Nakamura</a></h4>
171
163
  </td>
172
- <td id='helmut-januschka'>
173
- <a href='https://github.com/hjanuschka'>
174
- <img src='https://github.com/hjanuschka.png' width='140px;'>
175
- </a>
176
- <h4 align='center'><a href='https://twitter.com/hjanuschka'>Helmut Januschka</a></h4>
177
- </td>
178
- <td id='jorge-revuelta-h'>
179
- <a href='https://github.com/minuscorp'>
180
- <img src='https://github.com/minuscorp.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;'>
181
169
  </a>
182
- <h4 align='center'><a href='https://twitter.com/minuscorp'>Jorge Revuelta H</a></h4>
170
+ <h4 align='center'><a href='https://twitter.com/giginet'>Kohki Miki</a></h4>
183
171
  </td>
184
172
  <td id='stefan-natchev'>
185
173
  <a href='https://github.com/snatchev'>
@@ -187,19 +175,31 @@ If the above doesn't help, please [submit an issue](https://github.com/fastlane/
187
175
  </a>
188
176
  <h4 align='center'><a href='https://twitter.com/snatchev'>Stefan Natchev</a></h4>
189
177
  </td>
190
- <td id='felix-krause'>
191
- <a href='https://github.com/KrauseFx'>
192
- <img src='https://github.com/KrauseFx.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;'>
193
181
  </a>
194
- <h4 align='center'><a href='https://twitter.com/KrauseFx'>Felix Krause</a></h4>
182
+ <h4 align='center'><a href='https://twitter.com/mellis1995'>Matthew Ellis</a></h4>
183
+ </td>
184
+ <td id='manu-wallner'>
185
+ <a href='https://github.com/milch'>
186
+ <img src='https://github.com/milch.png' width='140px;'>
187
+ </a>
188
+ <h4 align='center'><a href='https://twitter.com/acrooow'>Manu Wallner</a></h4>
189
+ </td>
190
+ <td id='olivier-halligon'>
191
+ <a href='https://github.com/AliSoftware'>
192
+ <img src='https://github.com/AliSoftware.png' width='140px;'>
193
+ </a>
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='maksym-grebenets'>
199
- <a href='https://github.com/mgrebenets'>
200
- <img src='https://github.com/mgrebenets.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/mgrebenets'>Maksym Grebenets</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
@@ -1,5 +1,5 @@
1
1
  module Fastlane
2
- VERSION = '2.213.0'.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.213.0
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.116]
267
+ // FastlaneRunnerAPIVersion [0.9.117]
@@ -4204,6 +4204,61 @@ public func downloadFromPlayStore(packageName: String,
4204
4204
  _ = runner.executeCommand(command)
4205
4205
  }
4206
4206
 
4207
+ /**
4208
+ Download the Universal APK of a given version code from the Google Play Console
4209
+
4210
+ - parameters:
4211
+ - packageName: The package name of the application to use
4212
+ - versionCode: The versionCode for which to download the generated APK
4213
+ - jsonKey: The path to a file containing service account JSON, used to authenticate with Google
4214
+ - jsonKeyData: The raw service account JSON data used to authenticate with Google
4215
+ - rootUrl: Root URL for the Google Play API. The provided URL will be used for API calls in place of https://www.googleapis.com/
4216
+ - timeout: Timeout for read, open, and send (in seconds)
4217
+ - destination: The path on disk where to download the Generated Universal APK
4218
+ - certificateSha256Hash: The SHA256 hash of the signing key for which to download the Universal, Code-Signed APK for. Use 'xx:xx:xx:…' format (32 hex bytes separated by colons), as printed by `keytool -list -keystore <keystorefile>`. Only useful to provide if you have multiple signing keys configured on GPC, to specify which generated APK to download
4219
+
4220
+ - returns: 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
4221
+
4222
+ Download the universal APK of a given version code from the Google Play Console.
4223
+
4224
+ This uses fastlane `Supply` (and the `AndroidPublisher` Google API) to download the Universal APK
4225
+ generated by Google after you uploaded an `.aab` bundle to the Play Console.
4226
+
4227
+ See https://developers.google.com/android-publisher/api-ref/rest/v3/generatedapks/list
4228
+
4229
+ */
4230
+ public func downloadUniversalApkFromGooglePlay(packageName: String,
4231
+ versionCode: OptionalConfigValue<Int?> = .fastlaneDefault(nil),
4232
+ jsonKey: OptionalConfigValue<String?> = .fastlaneDefault(nil),
4233
+ jsonKeyData: OptionalConfigValue<String?> = .fastlaneDefault(nil),
4234
+ rootUrl: OptionalConfigValue<String?> = .fastlaneDefault(nil),
4235
+ timeout: Int = 300,
4236
+ destination: String,
4237
+ certificateSha256Hash: OptionalConfigValue<String?> = .fastlaneDefault(nil))
4238
+ {
4239
+ let packageNameArg = RubyCommand.Argument(name: "package_name", value: packageName, type: nil)
4240
+ let versionCodeArg = versionCode.asRubyArgument(name: "version_code", type: nil)
4241
+ let jsonKeyArg = jsonKey.asRubyArgument(name: "json_key", type: nil)
4242
+ let jsonKeyDataArg = jsonKeyData.asRubyArgument(name: "json_key_data", type: nil)
4243
+ let rootUrlArg = rootUrl.asRubyArgument(name: "root_url", type: nil)
4244
+ let timeoutArg = RubyCommand.Argument(name: "timeout", value: timeout, type: nil)
4245
+ let destinationArg = RubyCommand.Argument(name: "destination", value: destination, type: nil)
4246
+ let certificateSha256HashArg = certificateSha256Hash.asRubyArgument(name: "certificate_sha256_hash", type: nil)
4247
+ let array: [RubyCommand.Argument?] = [packageNameArg,
4248
+ versionCodeArg,
4249
+ jsonKeyArg,
4250
+ jsonKeyDataArg,
4251
+ rootUrlArg,
4252
+ timeoutArg,
4253
+ destinationArg,
4254
+ certificateSha256HashArg]
4255
+ let args: [RubyCommand.Argument] = array
4256
+ .filter { $0?.value != nil }
4257
+ .compactMap { $0 }
4258
+ let command = RubyCommand(commandID: "", methodName: "download_universal_apk_from_google_play", className: nil, args: args)
4259
+ _ = runner.executeCommand(command)
4260
+ }
4261
+
4207
4262
  /**
4208
4263
  Creates a zipped dSYM in the project root from the .xcarchive
4209
4264
 
@@ -10868,7 +10923,7 @@ public func ssh(username: String,
10868
10923
  - parameters:
10869
10924
  - packageName: The package name of the application to use
10870
10925
  - versionName: Version name (used when uploading new apks/aabs) - defaults to 'versionName' in build.gradle or AndroidManifest.xml
10871
- - versionCode: Version code (used when updating rollout or promoting specific versions)
10926
+ - versionCode: The versionCode for which to download the generated APK
10872
10927
  - releaseStatus: Release status (used when uploading new apks/aabs) - valid values are completed, draft, halted, inProgress
10873
10928
  - track: The track of the application to use. The default available tracks are: production, beta, alpha, internal
10874
10929
  - rollout: The percentage of the user fraction when uploading to the rollout track (setting to 1 will complete the rollout)
@@ -12595,7 +12650,7 @@ public func uploadToAppStore(apiKeyPath: OptionalConfigValue<String?> = .fastlan
12595
12650
  - parameters:
12596
12651
  - packageName: The package name of the application to use
12597
12652
  - versionName: Version name (used when uploading new apks/aabs) - defaults to 'versionName' in build.gradle or AndroidManifest.xml
12598
- - versionCode: Version code (used when updating rollout or promoting specific versions)
12653
+ - versionCode: The versionCode for which to download the generated APK
12599
12654
  - releaseStatus: Release status (used when uploading new apks/aabs) - valid values are completed, draft, halted, inProgress
12600
12655
  - track: The track of the application to use. The default available tracks are: production, beta, alpha, internal
12601
12656
  - rollout: The percentage of the user fraction when uploading to the rollout track (setting to 1 will complete the rollout)
@@ -13394,7 +13449,7 @@ public func xcov(workspace: OptionalConfigValue<String?> = .fastlaneDefault(nil)
13394
13449
  coverallsServiceJobId: OptionalConfigValue<String?> = .fastlaneDefault(nil),
13395
13450
  coverallsRepoToken: OptionalConfigValue<String?> = .fastlaneDefault(nil),
13396
13451
  xcconfig: OptionalConfigValue<String?> = .fastlaneDefault(nil),
13397
- ideFoundationPath: String = "/Applications/Xcode-14.1.0.app/Contents/Developer/../Frameworks/IDEFoundation.framework/Versions/A/IDEFoundation",
13452
+ ideFoundationPath: String = "/Applications/Xcode-14.3.0.app/Contents/Developer/../Frameworks/IDEFoundation.framework/Versions/A/IDEFoundation",
13398
13453
  legacySupport: OptionalConfigValue<Bool> = .fastlaneDefault(false))
13399
13454
  {
13400
13455
  let workspaceArg = workspace.asRubyArgument(name: "workspace", type: nil)
@@ -13597,4 +13652,4 @@ public let snapshotfile: Snapshotfile = .init()
13597
13652
 
13598
13653
  // Please don't remove the lines below
13599
13654
  // They are used to detect outdated files
13600
- // FastlaneRunnerAPIVersion [0.9.169]
13655
+ // FastlaneRunnerAPIVersion [0.9.170]
@@ -17,4 +17,4 @@ public class Gymfile: GymfileProtocol {
17
17
  // during the `init` process, and you won't see this message
18
18
  }
19
19
 
20
- // Generated with fastlane 2.213.0
20
+ // Generated with fastlane 2.214.0