fastlane 2.235.0 → 2.236.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 14907c8841271cfdc5ca71eeb8b413b39772478ec3691d1301fb1c4432dc9768
4
- data.tar.gz: eaf7da1b6040142a160972fe8f42a88bf4c10912375b217877262cba144707c0
3
+ metadata.gz: f129a659ef224d3a5367a5b69ff6a05e5bb9bf18f4034b8494a891804592438d
4
+ data.tar.gz: dca0b340e8cb13eac6472054edc5750cbdbe572b21180fda9c22c84f4cb8da44
5
5
  SHA512:
6
- metadata.gz: 29080ed1e5e25292a2a95dd9ae6e1def90246c84d4331d78a153818fc73f8bf1f67ee7a886e0e54b67966ffcf72c462088d197f213ca5e2d71f94c701146f4db
7
- data.tar.gz: 5bdea3d658146484366f97e4a52a301e0ec0a6aa203b616fc35676846865b27d3a9d1789991907639179268fc1b77ed24387c1ea82792e71945d17dff9af8480
6
+ metadata.gz: b24b41096b6ca155d1056a9d9ce9aed33ecd0e9eacc42ad03584fa5a341132a01c0f36e90087b7cfb78c4540e0412098285c06dbb08de3c1c8daf595d8181a29
7
+ data.tar.gz: 3c46b2adb30f65d2649c1ee4510d7f08e612b3fe9ff4c880f587edca2c0e82c1f840b508836ce72ee504bc36adedc9f5391d11bd2c5a548f1a145fe5ca637d7d
data/README.md CHANGED
@@ -36,29 +36,11 @@ If the above doesn't help, please [submit an issue](https://github.com/fastlane/
36
36
  <!-- This table is regenerated and resorted on each release -->
37
37
  <table id='team'>
38
38
  <tr>
39
- <td id='jimmy-dee'>
40
- <a href='https://github.com/jdee'>
41
- <img src='https://github.com/jdee.png' width='140px;'>
42
- </a>
43
- <h4 align='center'>Jimmy Dee</h4>
44
- </td>
45
- <td id='jérôme-lacoste'>
46
- <a href='https://github.com/lacostej'>
47
- <img src='https://github.com/lacostej.png' width='140px;'>
48
- </a>
49
- <h4 align='center'><a href='https://twitter.com/lacostej'>Jérôme Lacoste</a></h4>
50
- </td>
51
- <td id='stefan-natchev'>
52
- <a href='https://github.com/snatchev'>
53
- <img src='https://github.com/snatchev.png' width='140px;'>
54
- </a>
55
- <h4 align='center'><a href='https://twitter.com/snatchev'>Stefan Natchev</a></h4>
56
- </td>
57
- <td id='kohki-miki'>
58
- <a href='https://github.com/giginet'>
59
- <img src='https://github.com/giginet.png' width='140px;'>
39
+ <td id='fumiya-nakamura'>
40
+ <a href='https://github.com/nafu'>
41
+ <img src='https://github.com/nafu.png' width='140px;'>
60
42
  </a>
61
- <h4 align='center'><a href='https://twitter.com/giginet'>Kohki Miki</a></h4>
43
+ <h4 align='center'><a href='https://twitter.com/nafu003'>Fumiya Nakamura</a></h4>
62
44
  </td>
63
45
  <td id='iulian-onofrei'>
64
46
  <a href='https://github.com/revolter'>
@@ -66,57 +48,43 @@ If the above doesn't help, please [submit an issue](https://github.com/fastlane/
66
48
  </a>
67
49
  <h4 align='center'><a href='https://twitter.com/Revolt666'>Iulian Onofrei</a></h4>
68
50
  </td>
69
- </tr>
70
- <tr>
71
- <td id='manu-wallner'>
72
- <a href='https://github.com/milch'>
73
- <img src='https://github.com/milch.png' width='140px;'>
74
- </a>
75
- <h4 align='center'><a href='https://twitter.com/acrooow'>Manu Wallner</a></h4>
76
- </td>
77
51
  <td id='helmut-januschka'>
78
52
  <a href='https://github.com/hjanuschka'>
79
53
  <img src='https://github.com/hjanuschka.png' width='140px;'>
80
54
  </a>
81
55
  <h4 align='center'><a href='https://twitter.com/hjanuschka'>Helmut Januschka</a></h4>
82
56
  </td>
83
- <td id='roger-oba'>
84
- <a href='https://github.com/rogerluan'>
85
- <img src='https://github.com/rogerluan.png' width='140px;'>
86
- </a>
87
- <h4 align='center'><a href='https://twitter.com/rogerluan_'>Roger Oba</a></h4>
88
- </td>
89
- <td id='fumiya-nakamura'>
90
- <a href='https://github.com/nafu'>
91
- <img src='https://github.com/nafu.png' width='140px;'>
57
+ <td id='josh-holtz'>
58
+ <a href='https://github.com/joshdholtz'>
59
+ <img src='https://github.com/joshdholtz.png' width='140px;'>
92
60
  </a>
93
- <h4 align='center'><a href='https://twitter.com/nafu003'>Fumiya Nakamura</a></h4>
61
+ <h4 align='center'><a href='https://twitter.com/joshdholtz'>Josh Holtz</a></h4>
94
62
  </td>
95
- <td id='manish-rathi'>
96
- <a href='https://github.com/crazymanish'>
97
- <img src='https://github.com/crazymanish.png' width='140px;'>
63
+ <td id='connor-tumbleson'>
64
+ <a href='https://github.com/ibotpeaches'>
65
+ <img src='https://github.com/ibotpeaches.png' width='140px;'>
98
66
  </a>
99
- <h4 align='center'><a href='https://twitter.com/iammanishrathi'>Manish Rathi</a></h4>
67
+ <h4 align='center'><a href='https://twitter.com/ibotpeaches'>Connor Tumbleson</a></h4>
100
68
  </td>
101
69
  </tr>
102
70
  <tr>
103
- <td id='max-ott'>
104
- <a href='https://github.com/max-ott'>
105
- <img src='https://github.com/max-ott.png' width='140px;'>
71
+ <td id='aaron-brager'>
72
+ <a href='https://github.com/getaaron'>
73
+ <img src='https://github.com/getaaron.png' width='140px;'>
106
74
  </a>
107
- <h4 align='center'><a href='https://twitter.com/ott_max'>Max Ott</a></h4>
75
+ <h4 align='center'><a href='https://twitter.com/getaaron'>Aaron Brager</a></h4>
108
76
  </td>
109
- <td id='olivier-halligon'>
110
- <a href='https://github.com/AliSoftware'>
111
- <img src='https://github.com/AliSoftware.png' width='140px;'>
77
+ <td id='matthew-ellis'>
78
+ <a href='https://github.com/matthewellis'>
79
+ <img src='https://github.com/matthewellis.png' width='140px;'>
112
80
  </a>
113
- <h4 align='center'><a href='https://twitter.com/aligatr'>Olivier Halligon</a></h4>
81
+ <h4 align='center'><a href='https://twitter.com/mellis1995'>Matthew Ellis</a></h4>
114
82
  </td>
115
- <td id='daniel-jankowski'>
116
- <a href='https://github.com/mollyIV'>
117
- <img src='https://github.com/mollyIV.png' width='140px;'>
83
+ <td id='danielle-tomlinson'>
84
+ <a href='https://github.com/endocrimes'>
85
+ <img src='https://github.com/endocrimes.png' width='140px;'>
118
86
  </a>
119
- <h4 align='center'><a href='https://twitter.com/mollyIV'>Daniel Jankowski</a></h4>
87
+ <h4 align='center'><a href='https://twitter.com/endocrimes'>Danielle Tomlinson</a></h4>
120
88
  </td>
121
89
  <td id='andrew-mcburney'>
122
90
  <a href='https://github.com/armcburney'>
@@ -124,43 +92,43 @@ If the above doesn't help, please [submit an issue](https://github.com/fastlane/
124
92
  </a>
125
93
  <h4 align='center'><a href='https://twitter.com/armcburney'>Andrew McBurney</a></h4>
126
94
  </td>
127
- <td id='maksym-grebenets'>
128
- <a href='https://github.com/mgrebenets'>
129
- <img src='https://github.com/mgrebenets.png' width='140px;'>
95
+ <td id='olivier-halligon'>
96
+ <a href='https://github.com/AliSoftware'>
97
+ <img src='https://github.com/AliSoftware.png' width='140px;'>
130
98
  </a>
131
- <h4 align='center'><a href='https://twitter.com/mgrebenets'>Maksym Grebenets</a></h4>
99
+ <h4 align='center'><a href='https://twitter.com/aligatr'>Olivier Halligon</a></h4>
132
100
  </td>
133
101
  </tr>
134
102
  <tr>
135
- <td id='jorge-revuelta-h'>
136
- <a href='https://github.com/minuscorp'>
137
- <img src='https://github.com/minuscorp.png' width='140px;'>
103
+ <td id='kohki-miki'>
104
+ <a href='https://github.com/giginet'>
105
+ <img src='https://github.com/giginet.png' width='140px;'>
138
106
  </a>
139
- <h4 align='center'><a href='https://twitter.com/minuscorp'>Jorge Revuelta H</a></h4>
107
+ <h4 align='center'><a href='https://twitter.com/giginet'>Kohki Miki</a></h4>
140
108
  </td>
141
- <td id='aaron-brager'>
142
- <a href='https://github.com/getaaron'>
143
- <img src='https://github.com/getaaron.png' width='140px;'>
109
+ <td id='roger-oba'>
110
+ <a href='https://github.com/rogerluan'>
111
+ <img src='https://github.com/rogerluan.png' width='140px;'>
144
112
  </a>
145
- <h4 align='center'><a href='https://twitter.com/getaaron'>Aaron Brager</a></h4>
113
+ <h4 align='center'><a href='https://twitter.com/rogerluan_'>Roger Oba</a></h4>
146
114
  </td>
147
- <td id='josh-holtz'>
148
- <a href='https://github.com/joshdholtz'>
149
- <img src='https://github.com/joshdholtz.png' width='140px;'>
115
+ <td id='joshua-liebowitz'>
116
+ <a href='https://github.com/taquitos'>
117
+ <img src='https://github.com/taquitos.png' width='140px;'>
150
118
  </a>
151
- <h4 align='center'><a href='https://twitter.com/joshdholtz'>Josh Holtz</a></h4>
119
+ <h4 align='center'><a href='https://twitter.com/taquitos'>Joshua Liebowitz</a></h4>
152
120
  </td>
153
- <td id='satoshi-namai'>
154
- <a href='https://github.com/ainame'>
155
- <img src='https://github.com/ainame.png' width='140px;'>
121
+ <td id='manish-rathi'>
122
+ <a href='https://github.com/crazymanish'>
123
+ <img src='https://github.com/crazymanish.png' width='140px;'>
156
124
  </a>
157
- <h4 align='center'><a href='https://twitter.com/ainame'>Satoshi Namai</a></h4>
125
+ <h4 align='center'><a href='https://twitter.com/iammanishrathi'>Manish Rathi</a></h4>
158
126
  </td>
159
- <td id='matthew-ellis'>
160
- <a href='https://github.com/matthewellis'>
161
- <img src='https://github.com/matthewellis.png' width='140px;'>
127
+ <td id='jimmy-dee'>
128
+ <a href='https://github.com/jdee'>
129
+ <img src='https://github.com/jdee.png' width='140px;'>
162
130
  </a>
163
- <h4 align='center'><a href='https://twitter.com/mellis1995'>Matthew Ellis</a></h4>
131
+ <h4 align='center'>Jimmy Dee</h4>
164
132
  </td>
165
133
  </tr>
166
134
  <tr>
@@ -170,17 +138,43 @@ If the above doesn't help, please [submit an issue](https://github.com/fastlane/
170
138
  </a>
171
139
  <h4 align='center'><a href='https://twitter.com/lmirosevic'>Luka Mirosevic</a></h4>
172
140
  </td>
173
- <td id='connor-tumbleson'>
174
- <a href='https://github.com/ibotpeaches'>
175
- <img src='https://github.com/ibotpeaches.png' width='140px;'>
141
+ <td id='jorge-revuelta-h'>
142
+ <a href='https://github.com/minuscorp'>
143
+ <img src='https://github.com/minuscorp.png' width='140px;'>
176
144
  </a>
177
- <h4 align='center'><a href='https://twitter.com/ibotpeaches'>Connor Tumbleson</a></h4>
145
+ <h4 align='center'><a href='https://twitter.com/minuscorp'>Jorge Revuelta H</a></h4>
178
146
  </td>
179
- <td id='danielle-tomlinson'>
180
- <a href='https://github.com/endocrimes'>
181
- <img src='https://github.com/endocrimes.png' width='140px;'>
147
+ <td id='manu-wallner'>
148
+ <a href='https://github.com/milch'>
149
+ <img src='https://github.com/milch.png' width='140px;'>
182
150
  </a>
183
- <h4 align='center'><a href='https://twitter.com/endocrimes'>Danielle Tomlinson</a></h4>
151
+ <h4 align='center'><a href='https://twitter.com/acrooow'>Manu Wallner</a></h4>
152
+ </td>
153
+ <td id='łukasz-grabowski'>
154
+ <a href='https://github.com/lucgrabowski'>
155
+ <img src='https://github.com/lucgrabowski.png' width='140px;'>
156
+ </a>
157
+ <h4 align='center'>Łukasz Grabowski</h4>
158
+ </td>
159
+ <td id='stefan-natchev'>
160
+ <a href='https://github.com/snatchev'>
161
+ <img src='https://github.com/snatchev.png' width='140px;'>
162
+ </a>
163
+ <h4 align='center'><a href='https://twitter.com/snatchev'>Stefan Natchev</a></h4>
164
+ </td>
165
+ </tr>
166
+ <tr>
167
+ <td id='maksym-grebenets'>
168
+ <a href='https://github.com/mgrebenets'>
169
+ <img src='https://github.com/mgrebenets.png' width='140px;'>
170
+ </a>
171
+ <h4 align='center'><a href='https://twitter.com/mgrebenets'>Maksym Grebenets</a></h4>
172
+ </td>
173
+ <td id='satoshi-namai'>
174
+ <a href='https://github.com/ainame'>
175
+ <img src='https://github.com/ainame.png' width='140px;'>
176
+ </a>
177
+ <h4 align='center'><a href='https://twitter.com/ainame'>Satoshi Namai</a></h4>
184
178
  </td>
185
179
  <td id='felix-krause'>
186
180
  <a href='https://github.com/KrauseFx'>
@@ -188,26 +182,32 @@ If the above doesn't help, please [submit an issue](https://github.com/fastlane/
188
182
  </a>
189
183
  <h4 align='center'><a href='https://twitter.com/KrauseFx'>Felix Krause</a></h4>
190
184
  </td>
191
- <td id='joshua-liebowitz'>
192
- <a href='https://github.com/taquitos'>
193
- <img src='https://github.com/taquitos.png' width='140px;'>
185
+ <td id='max-ott'>
186
+ <a href='https://github.com/max-ott'>
187
+ <img src='https://github.com/max-ott.png' width='140px;'>
194
188
  </a>
195
- <h4 align='center'><a href='https://twitter.com/taquitos'>Joshua Liebowitz</a></h4>
189
+ <h4 align='center'><a href='https://twitter.com/ott_max'>Max Ott</a></h4>
190
+ </td>
191
+ <td id='daniel-jankowski'>
192
+ <a href='https://github.com/mollyIV'>
193
+ <img src='https://github.com/mollyIV.png' width='140px;'>
194
+ </a>
195
+ <h4 align='center'><a href='https://twitter.com/mollyIV'>Daniel Jankowski</a></h4>
196
196
  </td>
197
197
  </tr>
198
198
  <tr>
199
+ <td id='jérôme-lacoste'>
200
+ <a href='https://github.com/lacostej'>
201
+ <img src='https://github.com/lacostej.png' width='140px;'>
202
+ </a>
203
+ <h4 align='center'><a href='https://twitter.com/lacostej'>Jérôme Lacoste</a></h4>
204
+ </td>
199
205
  <td id='jan-piotrowski'>
200
206
  <a href='https://github.com/janpio'>
201
207
  <img src='https://github.com/janpio.png' width='140px;'>
202
208
  </a>
203
209
  <h4 align='center'><a href='https://twitter.com/Sujan'>Jan Piotrowski</a></h4>
204
210
  </td>
205
- <td id='łukasz-grabowski'>
206
- <a href='https://github.com/lucgrabowski'>
207
- <img src='https://github.com/lucgrabowski.png' width='140px;'>
208
- </a>
209
- <h4 align='center'>Łukasz Grabowski</h4>
210
- </td>
211
211
  </table>
212
212
 
213
213
  Special thanks to all [contributors](https://github.com/fastlane/fastlane/graphs/contributors) for extending and improving _fastlane_.
@@ -0,0 +1,210 @@
1
+ module Fastlane
2
+ module Actions
3
+ class UpdateAppAgeRatingAction < Action
4
+ def self.description
5
+ "Update your app's age rating on App Store Connect"
6
+ end
7
+
8
+ def self.details
9
+ "Updates only the age rating of your app on App Store Connect without touching " \
10
+ "any other metadata, screenshots, or binaries. Useful for CI pipelines that need " \
11
+ "to update age ratings independently of an app release. Supports both API key " \
12
+ "and Apple ID authentication."
13
+ end
14
+
15
+ def self.available_options
16
+ [
17
+ FastlaneCore::ConfigItem.new(
18
+ key: :api_key_path,
19
+ env_names: ["DELIVER_API_KEY_PATH", "APP_STORE_CONNECT_API_KEY_PATH"],
20
+ description: "Path to your App Store Connect API Key JSON file (https://docs.fastlane.tools/app-store-connect-api/)",
21
+ optional: true,
22
+ conflicting_options: %i[api_key],
23
+ verify_block: proc do |value|
24
+ UI.user_error!("Couldn't find API key JSON file at path '#{value}'") unless File.exist?(value)
25
+ end
26
+ ),
27
+ FastlaneCore::ConfigItem.new(
28
+ key: :api_key,
29
+ env_names: ["DELIVER_API_KEY", "APP_STORE_CONNECT_API_KEY"],
30
+ description: "Your App Store Connect API Key information (https://docs.fastlane.tools/app-store-connect-api/)",
31
+ optional: true,
32
+ conflicting_options: %i[api_key_path],
33
+ sensitive: true,
34
+ type: Hash
35
+ ),
36
+ FastlaneCore::ConfigItem.new(
37
+ key: :app_identifier,
38
+ env_name: "DELIVER_APP_IDENTIFIER",
39
+ description: "The bundle identifier of your app",
40
+ optional: false,
41
+ type: String,
42
+ code_gen_sensitive: true
43
+ ),
44
+ FastlaneCore::ConfigItem.new(
45
+ key: :username,
46
+ env_name: "DELIVER_USER",
47
+ description: "Your Apple ID username",
48
+ optional: true,
49
+ type: String
50
+ ),
51
+ FastlaneCore::ConfigItem.new(
52
+ key: :age_rating_config_path,
53
+ env_name: "DELIVER_AGE_RATING_CONFIG_PATH",
54
+ description: "Path to the JSON file containing the age rating configuration",
55
+ optional: false,
56
+ type: String,
57
+ verify_block: proc do |value|
58
+ UI.user_error!("Age rating configuration file not found at: '#{value}'") unless File.exist?(value)
59
+ end
60
+ ),
61
+ FastlaneCore::ConfigItem.new(
62
+ key: :team_id,
63
+ env_name: "FASTLANE_TEAM_ID",
64
+ description: "The ID of your App Store Connect team if you're in multiple teams",
65
+ optional: true,
66
+ type: String,
67
+ code_gen_sensitive: true
68
+ ),
69
+ FastlaneCore::ConfigItem.new(
70
+ key: :team_name,
71
+ env_name: "FASTLANE_TEAM_NAME",
72
+ description: "The name of your App Store Connect team if you're in multiple teams",
73
+ optional: true,
74
+ type: String
75
+ )
76
+ ]
77
+ end
78
+
79
+ def self.run(params)
80
+ require 'spaceship'
81
+ require 'json'
82
+
83
+ # Honour an API key that was set by app_store_connect_api_key earlier in the lane
84
+ params[:api_key] ||= Actions.lane_context[SharedValues::APP_STORE_CONNECT_API_KEY]
85
+
86
+ # Authenticate: API key takes priority, falls back to Apple ID session
87
+ token = Spaceship::ConnectAPI::Token.from(
88
+ hash: params[:api_key],
89
+ filepath: params[:api_key_path]
90
+ )
91
+
92
+ if token
93
+ UI.message("Creating authorization token for App Store Connect API")
94
+ Spaceship::ConnectAPI.token = token
95
+ else
96
+ UI.message("Login to App Store Connect (#{params[:username]})")
97
+ Spaceship::ConnectAPI.login(
98
+ params[:username],
99
+ nil,
100
+ use_portal: false,
101
+ use_tunes: true,
102
+ team_id: params[:team_id],
103
+ team_name: params[:team_name]
104
+ )
105
+ end
106
+
107
+ # Find the app by bundle identifier
108
+ app = Spaceship::ConnectAPI::App.find(params[:app_identifier])
109
+ UI.user_error!("Could not find app with identifier '#{params[:app_identifier]}'") unless app
110
+
111
+ # Fetch the editable app info
112
+ app_info = app.fetch_edit_app_info
113
+ unless app_info
114
+ UI.user_error!(
115
+ "Could not fetch editable app info for '#{params[:app_identifier]}'. " \
116
+ "Ensure the app is in an editable state in App Store Connect."
117
+ )
118
+ end
119
+
120
+ # Parse age rating config and map ITC keys to ASC keys
121
+ config_json = parse_config(params[:age_rating_config_path])
122
+ attributes = build_attributes(config_json)
123
+
124
+ # Fetch and update the age rating declaration
125
+ age_rating = app_info.fetch_age_rating_declaration
126
+ UI.user_error!("Could not fetch age rating declaration for '#{params[:app_identifier]}'") unless age_rating
127
+
128
+ UI.message("Updating age rating for '#{params[:app_identifier]}'...")
129
+ age_rating.update(attributes: attributes)
130
+ UI.success("Successfully updated age rating for '#{params[:app_identifier]}'")
131
+
132
+ true
133
+ end
134
+
135
+ #####################################################
136
+ # @!group Documentation
137
+ #####################################################
138
+
139
+ def self.example_code
140
+ [
141
+ '# Using App Store Connect API key (recommended for CI)
142
+ update_app_age_rating(
143
+ api_key_path: "fastlane/api_key.json",
144
+ app_identifier: "com.example.app",
145
+ age_rating_config_path: "fastlane/metadata/age_rating.json"
146
+ )',
147
+ '# Using Apple ID
148
+ update_app_age_rating(
149
+ username: "user@example.com",
150
+ app_identifier: "com.example.app",
151
+ age_rating_config_path: "fastlane/metadata/age_rating.json",
152
+ team_id: "ABC123456"
153
+ )',
154
+ '# Using the api_key hash returned by app_store_connect_api_key action
155
+ api_key = app_store_connect_api_key(
156
+ key_id: "D383SF739",
157
+ issuer_id: "6053b7fe-68a8-4acb-89be-165aa6465141",
158
+ key_filepath: "./AuthKey_D383SF739.p8"
159
+ )
160
+ update_app_age_rating(
161
+ api_key: api_key,
162
+ app_identifier: "com.example.app",
163
+ age_rating_config_path: "fastlane/metadata/age_rating.json"
164
+ )'
165
+ ]
166
+ end
167
+
168
+ def self.category
169
+ :app_store_connect
170
+ end
171
+
172
+ def self.authors
173
+ ["PratikPatil131"]
174
+ end
175
+
176
+ def self.return_value
177
+ "Returns true if the age rating was successfully updated"
178
+ end
179
+
180
+ def self.is_supported?(platform) # rubocop:disable Naming/PredicateName
181
+ # fastlane's Action interface mandates the method name `is_supported?`
182
+ %i[ios mac tvos].include?(platform)
183
+ end
184
+
185
+ #####################################################
186
+ # @!group Private helpers
187
+ #####################################################
188
+
189
+ def self.parse_config(config_path)
190
+ JSON.parse(File.read(config_path))
191
+ rescue JSON::ParserError => ex
192
+ UI.user_error!("Invalid JSON in age rating configuration file '#{config_path}': #{ex.message}")
193
+ rescue StandardError => ex
194
+ UI.user_error!("Could not read age rating configuration file '#{config_path}': #{ex.message}")
195
+ end
196
+ private_class_method :parse_config
197
+
198
+ def self.build_attributes(config_json)
199
+ attributes = config_json.each_with_object({}) do |(key, value), attrs|
200
+ new_key = Spaceship::ConnectAPI::AgeRatingDeclaration.map_key_from_itc(key)
201
+ new_value = Spaceship::ConnectAPI::AgeRatingDeclaration.map_value_from_itc(new_key, value)
202
+ attrs[new_key] = new_value
203
+ end
204
+ attributes, = Spaceship::ConnectAPI::AgeRatingDeclaration.map_deprecation_if_possible(attributes)
205
+ attributes
206
+ end
207
+ private_class_method :build_attributes
208
+ end
209
+ end
210
+ end
@@ -188,7 +188,7 @@ module Fastlane
188
188
  File.write(mkdocs_yml_path, mkdocs_yml.to_yaml)
189
189
 
190
190
  # Copy over the assets from the `actions/docs/assets` directory
191
- Dir[File.join(custom_action_docs_path, "assets", "*")].each do |current_asset_path|
191
+ Dir[File.join(Fastlane::ROOT, custom_action_docs_path, "assets", "*")].each do |current_asset_path|
192
192
  UI.message("Copying asset #{current_asset_path}")
193
193
  FileUtils.cp(current_asset_path, File.join(docs_dir, "img", "actions", File.basename(current_asset_path)))
194
194
  end
@@ -1,5 +1,5 @@
1
1
  module Fastlane
2
- VERSION = '2.235.0'.freeze
2
+ VERSION = '2.236.0'.freeze
3
3
  SUMMARY = "The easiest way to build and release mobile apps.".freeze
4
4
  DESCRIPTION = "The easiest way to automate beta deployments and releases for your iOS and Android apps".freeze
5
5
  MINIMUM_XCODE_RELEASE = "7.0".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.235.0
20
+ // Generated with fastlane 2.236.0
@@ -532,4 +532,4 @@ public extension DeliverfileProtocol {
532
532
 
533
533
  // Please don't remove the lines below
534
534
  // They are used to detect outdated files
535
- // FastlaneRunnerAPIVersion [0.9.148]
535
+ // FastlaneRunnerAPIVersion [0.9.149]
@@ -2260,6 +2260,7 @@ public func captureAndroidScreenshots(androidHome: OptionalConfigValue<String?>
2260
2260
  - testplan: The testplan associated with the scheme that should be used for testing
2261
2261
  - onlyTesting: Array of strings matching Test Bundle/Test Suite/Test Cases to run
2262
2262
  - skipTesting: Array of strings matching Test Bundle/Test Suite/Test Cases to skip
2263
+ - runRosettaSimulator: Run simulator in a Rosetta mode
2263
2264
  - xcodebuildFormatter: xcodebuild formatter to use (ex: 'xcbeautify', 'xcbeautify --quieter', 'xcpretty', 'xcpretty -test'). Use empty string (ex: '') to disable any formatter (More information: https://docs.fastlane.tools/best-practices/xcodebuild-formatters/)
2264
2265
  - xcprettyArgs: **DEPRECATED!** Use `xcodebuild_formatter: ''` instead - Additional xcpretty arguments
2265
2266
  - disableXcpretty: Disable xcpretty formatting of build
@@ -2313,6 +2314,7 @@ public func captureIosScreenshots(workspace: OptionalConfigValue<String?> = .fas
2313
2314
  testplan: OptionalConfigValue<String?> = .fastlaneDefault(nil),
2314
2315
  onlyTesting: Any? = nil,
2315
2316
  skipTesting: Any? = nil,
2317
+ runRosettaSimulator: OptionalConfigValue<Bool> = .fastlaneDefault(false),
2316
2318
  xcodebuildFormatter: String = "xcbeautify",
2317
2319
  xcprettyArgs: OptionalConfigValue<String?> = .fastlaneDefault(nil),
2318
2320
  disableXcpretty: OptionalConfigValue<Bool?> = .fastlaneDefault(nil),
@@ -2366,6 +2368,7 @@ public func captureIosScreenshots(workspace: OptionalConfigValue<String?> = .fas
2366
2368
  let testplanArg = testplan.asRubyArgument(name: "testplan", type: nil)
2367
2369
  let onlyTestingArg = RubyCommand.Argument(name: "only_testing", value: onlyTesting, type: nil)
2368
2370
  let skipTestingArg = RubyCommand.Argument(name: "skip_testing", value: skipTesting, type: nil)
2371
+ let runRosettaSimulatorArg = runRosettaSimulator.asRubyArgument(name: "run_rosetta_simulator", type: nil)
2369
2372
  let xcodebuildFormatterArg = RubyCommand.Argument(name: "xcodebuild_formatter", value: xcodebuildFormatter, type: nil)
2370
2373
  let xcprettyArgsArg = xcprettyArgs.asRubyArgument(name: "xcpretty_args", type: nil)
2371
2374
  let disableXcprettyArg = disableXcpretty.asRubyArgument(name: "disable_xcpretty", type: nil)
@@ -2418,6 +2421,7 @@ public func captureIosScreenshots(workspace: OptionalConfigValue<String?> = .fas
2418
2421
  testplanArg,
2419
2422
  onlyTestingArg,
2420
2423
  skipTestingArg,
2424
+ runRosettaSimulatorArg,
2421
2425
  xcodebuildFormatterArg,
2422
2426
  xcprettyArgsArg,
2423
2427
  disableXcprettyArg,
@@ -2481,6 +2485,7 @@ public func captureIosScreenshots(workspace: OptionalConfigValue<String?> = .fas
2481
2485
  - testplan: The testplan associated with the scheme that should be used for testing
2482
2486
  - onlyTesting: Array of strings matching Test Bundle/Test Suite/Test Cases to run
2483
2487
  - skipTesting: Array of strings matching Test Bundle/Test Suite/Test Cases to skip
2488
+ - runRosettaSimulator: Run simulator in a Rosetta mode
2484
2489
  - xcodebuildFormatter: xcodebuild formatter to use (ex: 'xcbeautify', 'xcbeautify --quieter', 'xcpretty', 'xcpretty -test'). Use empty string (ex: '') to disable any formatter (More information: https://docs.fastlane.tools/best-practices/xcodebuild-formatters/)
2485
2490
  - xcprettyArgs: **DEPRECATED!** Use `xcodebuild_formatter: ''` instead - Additional xcpretty arguments
2486
2491
  - disableXcpretty: Disable xcpretty formatting of build
@@ -2534,6 +2539,7 @@ public func captureScreenshots(workspace: OptionalConfigValue<String?> = .fastla
2534
2539
  testplan: OptionalConfigValue<String?> = .fastlaneDefault(nil),
2535
2540
  onlyTesting: Any? = nil,
2536
2541
  skipTesting: Any? = nil,
2542
+ runRosettaSimulator: OptionalConfigValue<Bool> = .fastlaneDefault(false),
2537
2543
  xcodebuildFormatter: String = "xcbeautify",
2538
2544
  xcprettyArgs: OptionalConfigValue<String?> = .fastlaneDefault(nil),
2539
2545
  disableXcpretty: OptionalConfigValue<Bool?> = .fastlaneDefault(nil),
@@ -2587,6 +2593,7 @@ public func captureScreenshots(workspace: OptionalConfigValue<String?> = .fastla
2587
2593
  let testplanArg = testplan.asRubyArgument(name: "testplan", type: nil)
2588
2594
  let onlyTestingArg = RubyCommand.Argument(name: "only_testing", value: onlyTesting, type: nil)
2589
2595
  let skipTestingArg = RubyCommand.Argument(name: "skip_testing", value: skipTesting, type: nil)
2596
+ let runRosettaSimulatorArg = runRosettaSimulator.asRubyArgument(name: "run_rosetta_simulator", type: nil)
2590
2597
  let xcodebuildFormatterArg = RubyCommand.Argument(name: "xcodebuild_formatter", value: xcodebuildFormatter, type: nil)
2591
2598
  let xcprettyArgsArg = xcprettyArgs.asRubyArgument(name: "xcpretty_args", type: nil)
2592
2599
  let disableXcprettyArg = disableXcpretty.asRubyArgument(name: "disable_xcpretty", type: nil)
@@ -2639,6 +2646,7 @@ public func captureScreenshots(workspace: OptionalConfigValue<String?> = .fastla
2639
2646
  testplanArg,
2640
2647
  onlyTestingArg,
2641
2648
  skipTestingArg,
2649
+ runRosettaSimulatorArg,
2642
2650
  xcodebuildFormatterArg,
2643
2651
  xcprettyArgsArg,
2644
2652
  disableXcprettyArg,
@@ -10637,6 +10645,7 @@ public func slather(buildDirectory: OptionalConfigValue<String?> = .fastlaneDefa
10637
10645
  - testplan: The testplan associated with the scheme that should be used for testing
10638
10646
  - onlyTesting: Array of strings matching Test Bundle/Test Suite/Test Cases to run
10639
10647
  - skipTesting: Array of strings matching Test Bundle/Test Suite/Test Cases to skip
10648
+ - runRosettaSimulator: Run simulator in a Rosetta mode
10640
10649
  - xcodebuildFormatter: xcodebuild formatter to use (ex: 'xcbeautify', 'xcbeautify --quieter', 'xcpretty', 'xcpretty -test'). Use empty string (ex: '') to disable any formatter (More information: https://docs.fastlane.tools/best-practices/xcodebuild-formatters/)
10641
10650
  - xcprettyArgs: **DEPRECATED!** Use `xcodebuild_formatter: ''` instead - Additional xcpretty arguments
10642
10651
  - disableXcpretty: Disable xcpretty formatting of build
@@ -10690,6 +10699,7 @@ public func snapshot(workspace: OptionalConfigValue<String?> = .fastlaneDefault(
10690
10699
  testplan: OptionalConfigValue<String?> = .fastlaneDefault(snapshotfile.testplan),
10691
10700
  onlyTesting: Any? = snapshotfile.onlyTesting,
10692
10701
  skipTesting: Any? = snapshotfile.skipTesting,
10702
+ runRosettaSimulator: OptionalConfigValue<Bool> = .fastlaneDefault(snapshotfile.runRosettaSimulator),
10693
10703
  xcodebuildFormatter: String = snapshotfile.xcodebuildFormatter,
10694
10704
  xcprettyArgs: OptionalConfigValue<String?> = .fastlaneDefault(snapshotfile.xcprettyArgs),
10695
10705
  disableXcpretty: OptionalConfigValue<Bool?> = .fastlaneDefault(snapshotfile.disableXcpretty),
@@ -10743,6 +10753,7 @@ public func snapshot(workspace: OptionalConfigValue<String?> = .fastlaneDefault(
10743
10753
  let testplanArg = testplan.asRubyArgument(name: "testplan", type: nil)
10744
10754
  let onlyTestingArg = RubyCommand.Argument(name: "only_testing", value: onlyTesting, type: nil)
10745
10755
  let skipTestingArg = RubyCommand.Argument(name: "skip_testing", value: skipTesting, type: nil)
10756
+ let runRosettaSimulatorArg = runRosettaSimulator.asRubyArgument(name: "run_rosetta_simulator", type: nil)
10746
10757
  let xcodebuildFormatterArg = RubyCommand.Argument(name: "xcodebuild_formatter", value: xcodebuildFormatter, type: nil)
10747
10758
  let xcprettyArgsArg = xcprettyArgs.asRubyArgument(name: "xcpretty_args", type: nil)
10748
10759
  let disableXcprettyArg = disableXcpretty.asRubyArgument(name: "disable_xcpretty", type: nil)
@@ -10795,6 +10806,7 @@ public func snapshot(workspace: OptionalConfigValue<String?> = .fastlaneDefault(
10795
10806
  testplanArg,
10796
10807
  onlyTestingArg,
10797
10808
  skipTestingArg,
10809
+ runRosettaSimulatorArg,
10798
10810
  xcodebuildFormatterArg,
10799
10811
  xcprettyArgsArg,
10800
10812
  disableXcprettyArg,
@@ -12125,6 +12137,51 @@ public func unlockKeychain(path: String = "login",
12125
12137
  _ = runner.executeCommand(command)
12126
12138
  }
12127
12139
 
12140
+ /**
12141
+ Update your app's age rating on App Store Connect
12142
+
12143
+ - parameters:
12144
+ - apiKeyPath: Path to your App Store Connect API Key JSON file (https://docs.fastlane.tools/app-store-connect-api/)
12145
+ - apiKey: Your App Store Connect API Key information (https://docs.fastlane.tools/app-store-connect-api/)
12146
+ - appIdentifier: The bundle identifier of your app
12147
+ - username: Your Apple ID username
12148
+ - ageRatingConfigPath: Path to the JSON file containing the age rating configuration
12149
+ - teamId: The ID of your App Store Connect team if you're in multiple teams
12150
+ - teamName: The name of your App Store Connect team if you're in multiple teams
12151
+
12152
+ - returns: Returns true if the age rating was successfully updated
12153
+
12154
+ Updates only the age rating of your app on App Store Connect without touching any other metadata, screenshots, or binaries. Useful for CI pipelines that need to update age ratings independently of an app release. Supports both API key and Apple ID authentication.
12155
+ */
12156
+ public func updateAppAgeRating(apiKeyPath: OptionalConfigValue<String?> = .fastlaneDefault(nil),
12157
+ apiKey: OptionalConfigValue<[String: Any]?> = .fastlaneDefault(nil),
12158
+ appIdentifier: String,
12159
+ username: OptionalConfigValue<String?> = .fastlaneDefault(nil),
12160
+ ageRatingConfigPath: String,
12161
+ teamId: OptionalConfigValue<String?> = .fastlaneDefault(nil),
12162
+ teamName: OptionalConfigValue<String?> = .fastlaneDefault(nil))
12163
+ {
12164
+ let apiKeyPathArg = apiKeyPath.asRubyArgument(name: "api_key_path", type: nil)
12165
+ let apiKeyArg = apiKey.asRubyArgument(name: "api_key", type: nil)
12166
+ let appIdentifierArg = RubyCommand.Argument(name: "app_identifier", value: appIdentifier, type: nil)
12167
+ let usernameArg = username.asRubyArgument(name: "username", type: nil)
12168
+ let ageRatingConfigPathArg = RubyCommand.Argument(name: "age_rating_config_path", value: ageRatingConfigPath, type: nil)
12169
+ let teamIdArg = teamId.asRubyArgument(name: "team_id", type: nil)
12170
+ let teamNameArg = teamName.asRubyArgument(name: "team_name", type: nil)
12171
+ let array: [RubyCommand.Argument?] = [apiKeyPathArg,
12172
+ apiKeyArg,
12173
+ appIdentifierArg,
12174
+ usernameArg,
12175
+ ageRatingConfigPathArg,
12176
+ teamIdArg,
12177
+ teamNameArg]
12178
+ let args: [RubyCommand.Argument] = array
12179
+ .filter { $0?.value != nil }
12180
+ .compactMap { $0 }
12181
+ let command = RubyCommand(commandID: "", methodName: "update_app_age_rating", className: nil, args: args)
12182
+ _ = runner.executeCommand(command)
12183
+ }
12184
+
12128
12185
  /**
12129
12186
  This action changes the app group identifiers in the entitlements file
12130
12187
 
@@ -14056,4 +14113,4 @@ public let snapshotfile: Snapshotfile = .init()
14056
14113
 
14057
14114
  // Please don't remove the lines below
14058
14115
  // They are used to detect outdated files
14059
- // FastlaneRunnerAPIVersion [0.9.201]
14116
+ // FastlaneRunnerAPIVersion [0.9.202]
@@ -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.235.0
20
+ // Generated with fastlane 2.236.0
@@ -392,4 +392,4 @@ public extension GymfileProtocol {
392
392
 
393
393
  // Please don't remove the lines below
394
394
  // They are used to detect outdated files
395
- // FastlaneRunnerAPIVersion [0.9.151]
395
+ // FastlaneRunnerAPIVersion [0.9.152]
@@ -17,4 +17,4 @@ public class Matchfile: MatchfileProtocol {
17
17
  // during the `init` process, and you won't see this message
18
18
  }
19
19
 
20
- // Generated with fastlane 2.235.0
20
+ // Generated with fastlane 2.236.0
@@ -406,4 +406,4 @@ public extension MatchfileProtocol {
406
406
 
407
407
  // Please don't remove the lines below
408
408
  // They are used to detect outdated files
409
- // FastlaneRunnerAPIVersion [0.9.145]
409
+ // FastlaneRunnerAPIVersion [0.9.146]
@@ -17,4 +17,4 @@ public class Precheckfile: PrecheckfileProtocol {
17
17
  // during the `init` process, and you won't see this message
18
18
  }
19
19
 
20
- // Generated with fastlane 2.235.0
20
+ // Generated with fastlane 2.236.0
@@ -84,4 +84,4 @@ public extension PrecheckfileProtocol {
84
84
 
85
85
  // Please don't remove the lines below
86
86
  // They are used to detect outdated files
87
- // FastlaneRunnerAPIVersion [0.9.144]
87
+ // FastlaneRunnerAPIVersion [0.9.145]
@@ -17,4 +17,4 @@ public class Scanfile: ScanfileProtocol {
17
17
  // during the `init` process, and you won't see this message
18
18
  }
19
19
 
20
- // Generated with fastlane 2.235.0
20
+ // Generated with fastlane 2.236.0
@@ -574,4 +574,4 @@ public extension ScanfileProtocol {
574
574
 
575
575
  // Please don't remove the lines below
576
576
  // They are used to detect outdated files
577
- // FastlaneRunnerAPIVersion [0.9.156]
577
+ // FastlaneRunnerAPIVersion [0.9.157]
@@ -17,4 +17,4 @@ public class Screengrabfile: ScreengrabfileProtocol {
17
17
  // during the `init` process, and you won't see this message
18
18
  }
19
19
 
20
- // Generated with fastlane 2.235.0
20
+ // Generated with fastlane 2.236.0
@@ -161,4 +161,4 @@ public extension ScreengrabfileProtocol {
161
161
 
162
162
  // Please don't remove the lines below
163
163
  // They are used to detect outdated files
164
- // FastlaneRunnerAPIVersion [0.9.146]
164
+ // FastlaneRunnerAPIVersion [0.9.147]
@@ -17,4 +17,4 @@ public class Snapshotfile: SnapshotfileProtocol {
17
17
  // during the `init` process, and you won't see this message
18
18
  }
19
19
 
20
- // Generated with fastlane 2.235.0
20
+ // Generated with fastlane 2.236.0
@@ -143,6 +143,9 @@ public protocol SnapshotfileProtocol: AnyObject {
143
143
  /// Array of strings matching Test Bundle/Test Suite/Test Cases to skip
144
144
  var skipTesting: String? { get }
145
145
 
146
+ /// Run simulator in a Rosetta mode
147
+ var runRosettaSimulator: Bool { get }
148
+
146
149
  /// xcodebuild formatter to use (ex: 'xcbeautify', 'xcbeautify --quieter', 'xcpretty', 'xcpretty -test'). Use empty string (ex: '') to disable any formatter (More information: https://docs.fastlane.tools/best-practices/xcodebuild-formatters/)
147
150
  var xcodebuildFormatter: String { get }
148
151
 
@@ -348,6 +351,10 @@ public extension SnapshotfileProtocol {
348
351
  return nil
349
352
  }
350
353
 
354
+ var runRosettaSimulator: Bool {
355
+ return false
356
+ }
357
+
351
358
  var xcodebuildFormatter: String {
352
359
  return "xcbeautify"
353
360
  }
@@ -371,4 +378,4 @@ public extension SnapshotfileProtocol {
371
378
 
372
379
  // Please don't remove the lines below
373
380
  // They are used to detect outdated files
374
- // FastlaneRunnerAPIVersion [0.9.140]
381
+ // FastlaneRunnerAPIVersion [0.9.141]
@@ -1,6 +1,7 @@
1
1
  require 'shellwords'
2
2
  require 'tmpdir'
3
3
  require 'fileutils'
4
+ require 'base64'
4
5
  require 'credentials_manager/account_manager'
5
6
  require 'securerandom'
6
7
 
@@ -83,9 +84,14 @@ module FastlaneCore
83
84
  else
84
85
  api_key[:key_dir] = Dir.mktmpdir("deliver-")
85
86
  end
86
- # Specified p8 needs to be generated to call altool or iTMSTransporter
87
+ # Specified p8 needs to be generated to call altool or iTMSTransporter.
88
+ # The key may be Base64 encoded (e.g. when passed via an ENV var); altool and
89
+ # iTMSTransporter expect the raw .p8 contents, so decode it first. Spaceship
90
+ # decodes on its own, but the transporter wrote the value verbatim before this,
91
+ # producing an unparsable key and a "bearer token invalid" error.
92
+ key_content = api_key[:is_key_content_base64] ? Base64.decode64(api_key[:key]) : api_key[:key]
87
93
  File.open(File.join(api_key[:key_dir], "AuthKey_#{api_key[:key_id]}.p8"), "wb") do |p8|
88
- p8.write(api_key[:key])
94
+ p8.write(key_content)
89
95
  end
90
96
  api_key
91
97
  end
@@ -308,6 +308,11 @@ module Snapshot
308
308
  verify_block: proc do |value|
309
309
  verify_type('skip_testing', [Array, String], value)
310
310
  end),
311
+ FastlaneCore::ConfigItem.new(key: :run_rosetta_simulator,
312
+ env_name: "SNAPSHOT_RUN_ROSETTA_SIMULATOR",
313
+ description: "Run simulator in a Rosetta mode",
314
+ type: Boolean,
315
+ default_value: false),
311
316
 
312
317
  FastlaneCore::ConfigItem.new(key: :xcodebuild_formatter,
313
318
  env_names: ["SNAPSHOT_XCODEBUILD_FORMATTER", "FASTLANE_XCODEBUILD_FORMATTER"],
@@ -89,16 +89,18 @@ module Snapshot
89
89
  os = 'iOS'
90
90
  end
91
91
 
92
- os_version = Snapshot.config[:ios_version] || Snapshot::LatestOsVersion.version(os)
92
+ requested_os_version = Snapshot.config[:ios_version]
93
93
 
94
94
  destinations = devices.map do |d|
95
- device = find_device(d, os_version)
95
+ device = find_device(d, requested_os_version)
96
96
  if device.nil?
97
- UI.user_error!("No device found named '#{d}' for version '#{os_version}'") if device.nil?
98
- elsif device.os_version != os_version
99
- UI.important("Using device named '#{device.name}' with version '#{device.os_version}' because no match was found for version '#{os_version}'")
97
+ message = "No device found named '#{d}'"
98
+ message += " for version '#{requested_os_version}'" if requested_os_version
99
+ UI.user_error!(message)
100
+ elsif requested_os_version && device.os_version != requested_os_version
101
+ UI.important("Using device named '#{device.name}' with version '#{device.os_version}' because no match was found for version '#{requested_os_version}'")
100
102
  end
101
- "-destination 'platform=#{os} Simulator,name=#{device.name},OS=#{device.os_version}'"
103
+ "-destination 'platform=#{os} Simulator,id=#{device.udid}'"
102
104
  end
103
105
 
104
106
  return [destinations.join(' ')]
@@ -37,6 +37,10 @@ module Snapshot
37
37
  # they are present at all
38
38
  options += config[:only_testing].map { |test_id| "-only-testing:#{test_id.shellescape}" } if config[:only_testing]
39
39
  options += config[:skip_testing].map { |test_id| "-skip-testing:#{test_id.shellescape}" } if config[:skip_testing]
40
+
41
+ # Explicitly run simulator in Rosetta (needed for Xcode 14.3 and up)
42
+ options << "ARCHS=x86_64" if config[:run_rosetta_simulator]
43
+
40
44
  return options
41
45
  end
42
46
 
@@ -40,10 +40,17 @@ module Spaceship
40
40
  command :spaceauth do |c|
41
41
  c.syntax = 'fastlane spaceship spaceauth'
42
42
  c.description = 'Authentication helper for spaceship/fastlane to work with Apple 2-Step/2FA'
43
- c.option('--copy_to_clipboard', 'Whether the session string should be copied to clipboard. For more info see https://docs.fastlane.tools/best-practices/continuous-integration/#storing-a-manually-verified-session-using-spaceauth`')
43
+ c.option('--copy_to_clipboard VALUE', 'Whether the session string should be copied to clipboard (true/false). For more info see https://docs.fastlane.tools/best-practices/continuous-integration/#storing-a-manually-verified-session-using-spaceauth`')
44
44
  c.option('--check_session', 'Check to see if there is a valid session (either in the cache or via FASTLANE_SESSION). Sets the exit code to 0 if the session is valid or 1 if not.') { Spaceship::Globals.check_session = true }
45
45
  c.action do |args, options|
46
- Spaceship::SpaceauthRunner.new(username: options.user, copy_to_clipboard: options.copy_to_clipboard).run
46
+ copy_to_clipboard = if options.copy_to_clipboard.nil?
47
+ nil
48
+ elsif %w(yes YES true TRUE on ON).include?(options.copy_to_clipboard.to_s)
49
+ true
50
+ elsif %w(no NO false FALSE off OFF).include?(options.copy_to_clipboard.to_s)
51
+ false
52
+ end
53
+ Spaceship::SpaceauthRunner.new(username: options.user, copy_to_clipboard: copy_to_clipboard).run
47
54
  end
48
55
  end
49
56
 
@@ -190,7 +190,7 @@ module Spaceship
190
190
 
191
191
  def valid_name_for(input)
192
192
  latinized = input.to_slug.transliterate
193
- latinized = latinized.gsub(/[^[:ascii:]]|[@&*"]/, '') # remove non-valid characters
193
+ latinized = latinized.gsub(/[^[:ascii:]]|[\.@&*"]/, '') # remove non-valid characters
194
194
  # Check if the input string was modified, since it might be empty now
195
195
  # (if it only contained non-latin symbols) or the duplicate of another app
196
196
  if latinized != input
metadata CHANGED
@@ -1,40 +1,40 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fastlane
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.235.0
4
+ version: 2.236.0
5
5
  platform: ruby
6
6
  authors:
7
- - Jorge Revuelta H
7
+ - Connor Tumbleson
8
8
  - Fumiya Nakamura
9
- - Manish Rathi
10
- - Olivier Halligon
11
- - Danielle Tomlinson
9
+ - Jérôme Lacoste
10
+ - Roger Oba
12
11
  - Matthew Ellis
13
- - Kohki Miki
14
- - Luka Mirosevic
15
- - Manu Wallner
16
- - Connor Tumbleson
12
+ - Maksym Grebenets
13
+ - Danielle Tomlinson
17
14
  - Jan Piotrowski
18
- - Max Ott
19
- - Roger Oba
20
- - Jérôme Lacoste
21
- - Łukasz Grabowski
22
- - Satoshi Namai
23
- - Josh Holtz
24
15
  - Andrew McBurney
25
- - Jimmy Dee
26
- - Felix Krause
27
- - Maksym Grebenets
16
+ - Daniel Jankowski
17
+ - Iulian Onofrei
28
18
  - Stefan Natchev
29
- - Joshua Liebowitz
19
+ - Łukasz Grabowski
20
+ - Felix Krause
21
+ - Manu Wallner
30
22
  - Helmut Januschka
31
- - Iulian Onofrei
32
- - Daniel Jankowski
23
+ - Luka Mirosevic
24
+ - Satoshi Namai
25
+ - Joshua Liebowitz
26
+ - Jorge Revuelta H
27
+ - Manish Rathi
28
+ - Kohki Miki
29
+ - Max Ott
33
30
  - Aaron Brager
31
+ - Jimmy Dee
32
+ - Olivier Halligon
33
+ - Josh Holtz
34
34
  autorequire:
35
35
  bindir: bin
36
36
  cert_chain: []
37
- date: 2026-05-26 00:00:00.000000000 Z
37
+ date: 2026-06-08 00:00:00.000000000 Z
38
38
  dependencies:
39
39
  - !ruby/object:Gem::Dependency
40
40
  name: addressable
@@ -438,7 +438,7 @@ dependencies:
438
438
  requirements:
439
439
  - - ">="
440
440
  - !ruby/object:Gem::Version
441
- version: 2.1.0
441
+ version: 2.10.3
442
442
  - - "<"
443
443
  - !ruby/object:Gem::Version
444
444
  version: '4'
@@ -448,7 +448,7 @@ dependencies:
448
448
  requirements:
449
449
  - - ">="
450
450
  - !ruby/object:Gem::Version
451
- version: 2.1.0
451
+ version: 2.10.3
452
452
  - - "<"
453
453
  - !ruby/object:Gem::Version
454
454
  version: '4'
@@ -472,6 +472,20 @@ dependencies:
472
472
  - - "<"
473
473
  - !ruby/object:Gem::Version
474
474
  version: 5.0.0
475
+ - !ruby/object:Gem::Dependency
476
+ name: multi_json
477
+ requirement: !ruby/object:Gem::Requirement
478
+ requirements:
479
+ - - "~>"
480
+ - !ruby/object:Gem::Version
481
+ version: '1.12'
482
+ type: :runtime
483
+ prerelease: false
484
+ version_requirements: !ruby/object:Gem::Requirement
485
+ requirements:
486
+ - - "~>"
487
+ - !ruby/object:Gem::Version
488
+ version: '1.12'
475
489
  - !ruby/object:Gem::Dependency
476
490
  name: multipart-post
477
491
  requirement: !ruby/object:Gem::Requirement
@@ -1149,6 +1163,7 @@ files:
1149
1163
  - fastlane/lib/fastlane/actions/twitter.rb
1150
1164
  - fastlane/lib/fastlane/actions/typetalk.rb
1151
1165
  - fastlane/lib/fastlane/actions/unlock_keychain.rb
1166
+ - fastlane/lib/fastlane/actions/update_app_age_rating.rb
1152
1167
  - fastlane/lib/fastlane/actions/update_app_group_identifiers.rb
1153
1168
  - fastlane/lib/fastlane/actions/update_app_identifier.rb
1154
1169
  - fastlane/lib/fastlane/actions/update_code_signing_settings.rb